Merge pull request #18 from nishaad78/monotonic_clock

Use Monotonic clock
This commit is contained in:
Skippy 2019-04-10 22:58:04 -05:00 committed by GitHub
commit 652d4f1b7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -12,7 +12,7 @@ import (
) )
var ( var (
// Epoch is set to the twitter snowflake epoch of Nov 04 2010 01:42:54 UTC // Epoch is set to the twitter snowflake epoch of Nov 04 2010 01:42:54 UTC in milliseconds
// You may customize this to set a different epoch for your application. // You may customize this to set a different epoch for your application.
Epoch int64 = 1288834974657 Epoch int64 = 1288834974657
@ -78,7 +78,8 @@ var ErrInvalidBase32 = errors.New("invalid base32")
// node // node
type Node struct { type Node struct {
mu sync.Mutex mu sync.Mutex
time int64 epoch time.Time
time time.Duration
node int64 node int64
step int64 step int64
@ -119,6 +120,10 @@ func NewNode(node int64) (*Node, error) {
return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10)) return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
} }
var curTime = time.Now()
// add time.Duration to curTime to make sure we use the monotonic clock if available
n.epoch = curTime.Add(time.Unix(Epoch/1000, (Epoch%1000)*1000000).Sub(curTime))
return &n, nil return &n, nil
} }
@ -127,14 +132,14 @@ func (n *Node) Generate() ID {
n.mu.Lock() n.mu.Lock()
now := time.Now().UnixNano() / 1000000 now := time.Since(n.epoch)
if n.time == now { if now-n.time < time.Millisecond {
n.step = (n.step + 1) & n.stepMask n.step = (n.step + 1) & n.stepMask
if n.step == 0 { if n.step == 0 {
for now <= n.time { for now-n.time < time.Millisecond {
now = time.Now().UnixNano() / 1000000 now = time.Since(n.epoch)
} }
} }
} else { } else {
@ -143,7 +148,7 @@ func (n *Node) Generate() ID {
n.time = now n.time = now
r := ID((now-Epoch)<<n.timeShift | r := ID((now.Nanoseconds()/1000000)<<n.timeShift |
(n.node << n.nodeShift) | (n.node << n.nodeShift) |
(n.step), (n.step),
) )
@ -267,7 +272,7 @@ func (f ID) IntBytes() [8]byte {
return b return b
} }
// Time returns an int64 unix timestamp of the snowflake ID time // Time returns an int64 unix timestamp in milliseconds of the snowflake ID time
// DEPRECATED: the below function will be removed in a future release. // DEPRECATED: the below function will be removed in a future release.
func (f ID) Time() int64 { func (f ID) Time() int64 {
return (int64(f) >> timeShift) + Epoch return (int64(f) >> timeShift) + Epoch