You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
snowflake/internal/generator/generator.go

65 lines
1.6 KiB

package generator
import (
"errors"
"time"
)
var EPOCH_TIME time.Time = time.Unix(0, 1609459200000*int64(time.Millisecond))
var TIME_MASK uint64 = 0x1FFFFFFFFFF
var tooManyRequests = errors.New("Too many requests in the current ms")
var incorrectSystemTime = errors.New("The current time is less than the last generated time! Check the system time.")
type Generator struct {
LastGeneratedTime time.Duration
Counter uint64
LastCounterRollover time.Duration
WorkerID uint64
}
func (g *Generator) GenerateSnowflake() (uint64, error) {
time := time.Since(EPOCH_TIME)
if time < g.LastGeneratedTime {
return 0, incorrectSystemTime
}
if g.Counter == 4095 {
if g.LastCounterRollover >= time {
return 0, tooManyRequests
}
g.LastCounterRollover = time
g.Counter = 0
} else {
g.Counter += 1
}
g.LastGeneratedTime = time
return (((uint64(time.Milliseconds()) & TIME_MASK) << 22) + g.WorkerID + g.Counter), nil
}
func CreateGenerator(workerID uint64) (*Generator, error) {
if workerID <= 0 {
return nil, errors.New("Worker ID must be greater than 0")
}
return &Generator{
LastGeneratedTime: time.Since(EPOCH_TIME),
Counter: 0,
LastCounterRollover: time.Since(EPOCH_TIME),
WorkerID: workerID,
}, nil
}
func (g *Generator) Run(request chan chan uint64) {
for output := range request {
id, err := g.GenerateSnowflake()
if err != nil {
if err == tooManyRequests {
time.Sleep(time.Millisecond)
continue
} else if err == incorrectSystemTime {
panic("System time is incorrect")
}
}
output <- id
}
}