diff --git a/README.md b/README.md index 0e6cdab..bde8b0f 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,12 @@ func (sf *Sonyflake) NextID() (uint64, error) NextID can continue to generate IDs for about 174 years from StartTime. But after the Sonyflake time is over the limit, NextID returns an error. +if you want to use the mono time, you can call the method NextIDMono. + +```go +func (sf *Sonyflake) NextIDMono() (uint64, error) +``` +NextIDMono can avoid the clock backwards. > **Note:** > Sonyflake currently does not use the most significant bit of IDs, > so you can convert Sonyflake IDs from `uint64` to `int64` safely. diff --git a/sonyflake.go b/sonyflake.go index 548b243..a335824 100644 --- a/sonyflake.go +++ b/sonyflake.go @@ -45,11 +45,12 @@ type Settings struct { // Sonyflake is a distributed unique ID generator. type Sonyflake struct { - mutex *sync.Mutex - startTime int64 - elapsedTime int64 - sequence uint16 - machineID uint16 + mutex *sync.Mutex + startTime int64 + startTimeMono time.Time + elapsedTime int64 + sequence uint16 + machineID uint16 } var ( @@ -77,8 +78,10 @@ func New(st Settings) (*Sonyflake, error) { if st.StartTime.IsZero() { sf.startTime = toSonyflakeTime(time.Date(2014, 9, 1, 0, 0, 0, 0, time.UTC)) + sf.startTimeMono = time.Now() } else { sf.startTime = toSonyflakeTime(st.StartTime) + sf.startTimeMono = st.StartTime } var err error @@ -132,6 +135,31 @@ func (sf *Sonyflake) NextID() (uint64, error) { return sf.toID() } +// NextIDMono generates a next unique ID. +// After the Sonyflake time overflows, NextID returns an error. +// This function use mono time to avoid clock backwards +func (sf *Sonyflake) NextIDMono() (uint64, error) { + const maskSequence = uint16(1< sleepTime+sonyflakeTimeUnit { + t.Errorf("unexpected time: %d", actualTime) + } + + actualSequence := SequenceNumber(id) + if actualSequence != 0 { + t.Errorf("unexpected sequence: %d", actualSequence) + } + + actualMachineID := MachineID(id) + if actualMachineID != machineID { + t.Errorf("unexpected machine id: %d", actualMachineID) + } + + fmt.Println("sonyflake id:", id) + fmt.Println("decompose:", Decompose(id)) +}