Files
resume/pkg/idgen/idgen.go
T

76 lines
1.2 KiB
Go

package idgen
import (
"crypto/rand"
"fmt"
"sync"
"time"
)
var (
generator *FlakeIDGenerator
once sync.Once
)
type FlakeIDGenerator struct {
mu sync.Mutex
lastTs int64
seq int64
nodeID int64
}
func NewFlakeIDGenerator(nodeID int64) *FlakeIDGenerator {
return &FlakeIDGenerator{
nodeID: nodeID,
}
}
func (g *FlakeIDGenerator) GetID() (string, error) {
g.mu.Lock()
defer g.mu.Unlock()
now := time.Now().UnixNano() / 1e6
if now < g.lastTs {
return "", fmt.Errorf("clock moved backwards")
}
if now == g.lastTs {
g.seq++
if g.seq >= 1024 {
for now <= g.lastTs {
now = time.Now().UnixNano() / 1e6
}
g.seq = 0
}
} else {
g.seq = 0
}
g.lastTs = now
id := (now << 22) | (g.nodeID << 10) | g.seq
return fmt.Sprintf("%d", id), nil
}
func GetID() (string, error) {
once.Do(func() {
nodeID := int64(1)
b := make([]byte, 2)
_, err := rand.Read(b)
if err == nil {
nodeID = int64(b[0])<<8 | int64(b[1])
nodeID &= 0x3FF
}
generator = NewFlakeIDGenerator(nodeID)
})
return generator.GetID()
}
func MustGetID() string {
id, err := GetID()
if err != nil {
return fmt.Sprintf("%d", time.Now().UnixNano())
}
return id
}