package store import ( "sync" "time" ) // Snowflake — генератор сортируемых идентификаторов (AGENT.md 6.4): // 41 бит времени от эпохи 2026-01-01T00:00:00Z, 10 бит узла, 12 бит счётчика. type Snowflake struct { mu sync.Mutex epoch int64 node int64 lastMs int64 sequence int64 now func() time.Time } const ( snowflakeEpochMs = int64(1767225600000) // 2026-01-01T00:00:00Z nodeBits = 10 sequenceBits = 12 maxNode = (1 << nodeBits) - 1 maxSequence = (1 << sequenceBits) - 1 ) func NewSnowflake(node uint16) *Snowflake { return &Snowflake{ epoch: snowflakeEpochMs, node: int64(node) & maxNode, now: func() time.Time { return time.Now().UTC() }, } } // Next возвращает монотонно возрастающий идентификатор. func (s *Snowflake) Next() uint64 { s.mu.Lock() defer s.mu.Unlock() nowMs := s.now().UnixMilli() if nowMs < s.lastMs { // Часы ушли назад: продолжаем с последней метки, чтобы не выдать дубль. nowMs = s.lastMs } if nowMs == s.lastMs { s.sequence = (s.sequence + 1) & maxSequence if s.sequence == 0 { // Счётчик переполнен в эту миллисекунду — ждём следующую. for nowMs <= s.lastMs { time.Sleep(time.Millisecond) nowMs = s.now().UnixMilli() } } } else { s.sequence = 0 } s.lastMs = nowMs id := ((nowMs - s.epoch) << (nodeBits + sequenceBits)) | (s.node << sequenceBits) | s.sequence return uint64(id) } // SnowflakeTime возвращает время создания идентификатора. func SnowflakeTime(id uint64) time.Time { ms := int64(id>>(nodeBits+sequenceBits)) + snowflakeEpochMs return time.UnixMilli(ms).UTC() }