snowflake

Snowflake ID Generator
git clone git://git.lair.cx/snowflake
Log | Files | Refs | LICENSE

generator.go (809B)


      1 package snowflakes
      2 
      3 import (
      4 	"sync"
      5 	"time"
      6 )
      7 
      8 type Generator struct {
      9 	sync.Mutex
     10 
     11 	NodeID uint64
     12 	Epoch  int64
     13 
     14 	lastGen  int64
     15 	sequence uint64
     16 }
     17 
     18 func New(id uint64) *Generator {
     19 	return &Generator{
     20 		NodeID: id,
     21 	}
     22 }
     23 
     24 func NewWithEpoch(id uint64, epoch time.Time) *Generator {
     25 	return &Generator{
     26 		NodeID: id,
     27 		Epoch:  epoch.UnixMilli(),
     28 	}
     29 }
     30 
     31 func (g *Generator) Next() uint64 {
     32 	g.Lock()
     33 	defer g.Unlock()
     34 
     35 	now := time.Now().UnixMilli() - g.Epoch
     36 	if now < 0 {
     37 		panic("system time can not be older than epoch")
     38 	}
     39 
     40 	// "now" can be past, but we won't wait.
     41 
     42 	if g.lastGen < now {
     43 		g.lastGen = now
     44 		g.sequence = 0
     45 	} else if g.sequence == 0x0FFF {
     46 		g.lastGen++
     47 		g.sequence = 0
     48 	} else {
     49 		g.sequence++
     50 	}
     51 
     52 	return uint64(g.lastGen)&0x1FFFFFFFFFF<<22 + g.NodeID&0x03FF<<12 + g.sequence&0x0FFF
     53 }