54 lines
923 B
Go
54 lines
923 B
Go
|
package idgen
|
||
|
|
||
|
import (
|
||
|
"crypto/rand"
|
||
|
"encoding/base32"
|
||
|
"sync"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// Creates a new, random token.
|
||
|
func NewToken() string {
|
||
|
buf := make([]byte, 20)
|
||
|
_, err := rand.Read(buf)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
return base32.StdEncoding.EncodeToString(buf)
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
lock sync.Mutex
|
||
|
ts int64 = time.Now().Unix()
|
||
|
counter int64 = 1
|
||
|
counterMax int64 = 1 << 20
|
||
|
)
|
||
|
|
||
|
// NextID can generate ~1M ints per second for a given nodeID.
|
||
|
//
|
||
|
// nodeID must be less than 64.
|
||
|
func NextID(nodeID int64) int64 {
|
||
|
lock.Lock()
|
||
|
defer lock.Unlock()
|
||
|
|
||
|
tt := time.Now().Unix()
|
||
|
if tt > ts {
|
||
|
ts = tt
|
||
|
counter = 1
|
||
|
} else {
|
||
|
counter++
|
||
|
if counter == counterMax {
|
||
|
panic("Too many IDs.")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (ts << 26) + (nodeID << 20) + counter
|
||
|
}
|
||
|
|
||
|
func SplitID(id int64) (unixTime, nodeID, counter int64) {
|
||
|
counter = id & (0x00000000000FFFFF)
|
||
|
nodeID = (id >> 20) & (0x000000000000003F)
|
||
|
unixTime = id >> 26
|
||
|
return
|
||
|
}
|