package snowflake
import (
"sync"
"time"
)
const (
// 節點 ID 的位數 (0-1023)
nodeBits uint8 = 10
// Index 的位數 (0-4095)
indexBits uint8 = 12
// Index的最大值 用於檢測益出 (4095)
indexMax int64 = -1 ^ (-1 << indexBits)
// 時間戳向左偏移量 (22位)
timeShift = nodeBits + indexBits
// // 節點 ID 向左的偏移量 (10位)
nodeShift = indexBits
// 2018-12-03 12:00:08
epoch int64 = 1543809608000
)
type NodeStruct struct {
mutex sync.Mutex
timestamp int64
nodeType int64
index int64
}
func Node(nodeType int64) *NodeStruct {
// 返回 node 實例指針
return &NodeStruct{
timestamp: 0,
nodeType: nodeType,
index: 0,
}
}
func (ns *NodeStruct) Generate() int {
// 生成時加鎖
ns.mutex.Lock()
// 完成時解鎖
defer ns.mutex.Unlock()
// 取得當前時間戳
now := time.Now().UnixNano() / 1e6
if ns.timestamp == now{
ns.index ++
// 當前 index 用完
if ns.index > indexMax {
// 等待本毫秒结束
for now <= ns.timestamp {
now = time.Now().UnixNano() / 1e6
}
}
} else {
ns.index = 0
ns.timestamp = now
}
// 位移運算生成 ID
result := int( (now - epoch) << timeShift | (ns.nodeType << nodeShift) | (ns.index) )
return result
}
func Inverse (nodeId int) *NodeStruct {
// 返回 node 實例指針
return &NodeStruct{
timestamp: int64((nodeId >> timeShift) + int(epoch) ),
nodeType: int64((nodeId >> indexBits) - (nodeId >> timeShift << nodeBits )),
index: int64( (nodeId) - (nodeId >> indexBits << indexBits ) ),
}
}