diff --git a/snowflake.go b/snowflake.go index a5952a9..614c3ab 100644 --- a/snowflake.go +++ b/snowflake.go @@ -12,7 +12,7 @@ import ( ) 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. Epoch int64 = 1288834974657 @@ -77,10 +77,11 @@ var ErrInvalidBase32 = errors.New("invalid base32") // A Node struct holds the basic information needed for a snowflake generator // node type Node struct { - mu sync.Mutex - time int64 - node int64 - step int64 + mu sync.Mutex + epoch time.Time + time time.Duration + node int64 + step int64 nodeMax int64 nodeMask 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)) } + 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 } @@ -127,14 +132,14 @@ func (n *Node) Generate() ID { 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 if n.step == 0 { - for now <= n.time { - now = time.Now().UnixNano() / 1000000 + for now-n.time < time.Millisecond { + now = time.Since(n.epoch) } } } else { @@ -143,7 +148,7 @@ func (n *Node) Generate() ID { n.time = now - r := ID((now-Epoch)<> timeShift) + Epoch