11// Package sonyflake implements Sonyflake, a distributed unique ID generator inspired by Twitter's Snowflake.
22//
3- // A Sonyflake ID is composed of
3+ // By default, a Sonyflake ID is composed of
44//
55// 39 bits for time in units of 10 msec
66// 8 bits for a sequence number
@@ -16,18 +16,19 @@ import (
1616 "github.com/sony/sonyflake/v2/types"
1717)
1818
19- // These constants are the bit lengths of Sonyflake ID parts.
20- const (
21- BitLenTime = 39 // bit length of time
22- BitLenSequence = 8 // bit length of sequence number
23- BitLenMachine = 63 - BitLenTime - BitLenSequence // bit length of machine id
24- )
25-
2619// Settings configures Sonyflake:
2720//
21+ // BitsSequence is the bit length of a sequence number.
22+ // If BitsSequence is 0, the default bit length is used, which is 8.
23+ // If BitsSequence is 31 or more, an error is returned.
24+ //
25+ // BitsMachineID is the bit length of a machine ID.
26+ // If BitsMachineID is 0, the default bit length is used, which is 16.
27+ // If BitsMachineID is 31 or more, an error is returned.
28+ //
2829// TimeUnit is the time unit of Sonyflake.
2930// If TimeUnit is 0, the default time unit is used, which is 10 msec.
30- // TimeUnit must be equal to or greater than 1 msec .
31+ // TimeUnit must be 1 msec or longer .
3132//
3233// StartTime is the time since which the Sonyflake time is defined as the elapsed time.
3334// If StartTime is 0, the start time of the Sonyflake instance is set to "2025-01-01 00:00:00 +0000 UTC".
@@ -40,7 +41,12 @@ const (
4041// CheckMachineID validates the uniqueness of a machine ID.
4142// If CheckMachineID returns false, the instance will not be created.
4243// If CheckMachineID is nil, no validation is done.
44+ //
45+ // The bit length of time is calculated by 63 - BitsSequence - BitsMachineID.
46+ // If it is less than 32, an error is returned.
4347type Settings struct {
48+ BitsSequence int
49+ BitsMachineID int
4450 TimeUnit time.Duration
4551 StartTime time.Time
4652 MachineID func () (int , error )
@@ -49,46 +55,88 @@ type Settings struct {
4955
5056// Sonyflake is a distributed unique ID generator.
5157type Sonyflake struct {
52- mutex * sync.Mutex
58+ mutex * sync.Mutex
59+
60+ bitsTime int
61+ bitsSequence int
62+ bitsMachine int
63+
5364 timeUnit int64
5465 startTime int64
5566 elapsedTime int64
56- sequence int
57- machine int
67+
68+ sequence int
69+ machine int
5870}
5971
6072var (
61- ErrStartTimeAhead = errors .New ("start time is ahead of now" )
62- ErrNoPrivateAddress = errors .New ("no private ip address" )
63- ErrOverTimeLimit = errors .New ("over the time limit" )
64- ErrInvalidMachineID = errors .New ("invalid machine id" )
65- ErrInvalidTimeUnit = errors .New ("invalid time unit" )
73+ ErrInvalidBitsTime = errors .New ("bit length for time must be 32 or more" )
74+ ErrInvalidBitsSequence = errors .New ("invalid bit length for sequence number" )
75+ ErrInvalidBitsMachineID = errors .New ("invalid bit length for machine id" )
76+ ErrInvalidTimeUnit = errors .New ("invalid time unit" )
77+ ErrInvalidMachineID = errors .New ("invalid machine id" )
78+ ErrStartTimeAhead = errors .New ("start time is ahead of now" )
79+ ErrOverTimeLimit = errors .New ("over the time limit" )
80+ ErrNoPrivateAddress = errors .New ("no private ip address" )
6681)
6782
68- const defaultTimeUnit = 1e7 // nsec, i.e. 10 msec
83+ const (
84+ defaultTimeUnit = 1e7 // nsec, i.e. 10 msec
85+
86+ defaultBitsTime = 39
87+ defaultBitsSequence = 8
88+ defaultBitsMachine = 16
89+ )
6990
7091var defaultInterfaceAddrs = net .InterfaceAddrs
7192
7293// New returns a new Sonyflake configured with the given Settings.
7394// New returns an error in the following cases:
95+ // - Settings.BitsSequence is less than 0 or greater than 30.
96+ // - Settings.BitsMachineID is less than 0 or greater than 30.
97+ // - Settings.BitsSequence + Settings.BitsMachineID is 32 or more.
98+ // - Settings.TimeUnit is less than 1 msec.
7499// - Settings.StartTime is ahead of the current time.
75100// - Settings.MachineID returns an error.
76101// - Settings.CheckMachineID returns false.
77102func New (st Settings ) (* Sonyflake , error ) {
103+ if st .BitsSequence < 0 || st .BitsSequence > 30 {
104+ return nil , ErrInvalidBitsSequence
105+ }
106+ if st .BitsMachineID < 0 || st .BitsMachineID > 30 {
107+ return nil , ErrInvalidBitsMachineID
108+ }
109+ if st .TimeUnit < 0 || (st .TimeUnit > 0 && st .TimeUnit < time .Millisecond ) {
110+ return nil , ErrInvalidTimeUnit
111+ }
78112 if st .StartTime .After (time .Now ()) {
79113 return nil , ErrStartTimeAhead
80114 }
81115
82116 sf := new (Sonyflake )
83117 sf .mutex = new (sync.Mutex )
84- sf .sequence = 1 << BitLenSequence - 1
118+
119+ if st .BitsSequence == 0 {
120+ sf .bitsSequence = defaultBitsSequence
121+ } else {
122+ sf .bitsSequence = st .BitsSequence
123+ }
124+
125+ if st .BitsMachineID == 0 {
126+ sf .bitsMachine = defaultBitsMachine
127+ } else {
128+ sf .bitsMachine = st .BitsMachineID
129+ }
130+
131+ sf .bitsTime = 63 - sf .bitsSequence - sf .bitsMachine
132+ if sf .bitsTime < 32 {
133+ return nil , ErrInvalidBitsTime
134+ }
85135
86136 if st .TimeUnit == 0 {
87137 sf .timeUnit = defaultTimeUnit
88- } else if st .TimeUnit >= time .Millisecond {
89- sf .timeUnit = int64 (st .TimeUnit )
90138 } else {
91- return nil , ErrInvalidTimeUnit
139+ sf . timeUnit = int64 ( st . TimeUnit )
92140 }
93141
94142 if st .StartTime .IsZero () {
@@ -97,6 +145,8 @@ func New(st Settings) (*Sonyflake, error) {
97145 sf .startTime = sf .toInternalTime (st .StartTime )
98146 }
99147
148+ sf .sequence = 1 << sf .bitsSequence - 1
149+
100150 var err error
101151 if st .MachineID == nil {
102152 sf .machine , err = lower16BitPrivateIP (defaultInterfaceAddrs )
@@ -117,7 +167,7 @@ func New(st Settings) (*Sonyflake, error) {
117167// NextID generates a next unique ID as int64.
118168// After the Sonyflake time overflows, NextID returns an error.
119169func (sf * Sonyflake ) NextID () (int64 , error ) {
120- const maskSequence = 1 << BitLenSequence - 1
170+ maskSequence : = 1 << sf . bitsSequence - 1
121171
122172 sf .mutex .Lock ()
123173 defer sf .mutex .Unlock ()
@@ -153,12 +203,12 @@ func (sf *Sonyflake) sleep(overtime int64) {
153203}
154204
155205func (sf * Sonyflake ) toID () (int64 , error ) {
156- if sf .elapsedTime >= 1 << BitLenTime {
206+ if sf .elapsedTime >= 1 << sf . bitsTime {
157207 return 0 , ErrOverTimeLimit
158208 }
159209
160- return sf .elapsedTime << (BitLenSequence + BitLenMachine ) |
161- int64 (sf .sequence )<< BitLenMachine |
210+ return sf .elapsedTime << (sf . bitsSequence + sf . bitsMachine ) |
211+ int64 (sf .sequence )<< sf . bitsMachine |
162212 int64 (sf .machine ), nil
163213}
164214
@@ -198,35 +248,32 @@ func lower16BitPrivateIP(interfaceAddrs types.InterfaceAddrs) (int, error) {
198248}
199249
200250func (sf * Sonyflake ) ToTime (id int64 ) time.Time {
201- return time .Unix (0 , (sf .startTime + Time (id ))* sf .timeUnit )
202- }
203-
204- // Time returns the Sonyflake time when the given ID was generated.
205- func Time (id int64 ) int64 {
206- return id >> (BitLenSequence + BitLenMachine )
207- }
208-
209- // SequenceNumber returns the sequence number of a Sonyflake ID.
210- func SequenceNumber (id int64 ) int {
211- const maskSequence = int64 ((1 << BitLenSequence - 1 ) << BitLenMachine )
212- return int ((id & maskSequence ) >> BitLenMachine )
213- }
214-
215- // MachineID returns the machine ID of a Sonyflake ID.
216- func MachineID (id int64 ) int {
217- const maskMachine = int64 (1 << BitLenMachine - 1 )
218- return int (id & maskMachine )
251+ return time .Unix (0 , (sf .startTime + sf .timePart (id ))* sf .timeUnit )
219252}
220253
221254// Decompose returns a set of Sonyflake ID parts.
222- func Decompose (id int64 ) map [string ]int64 {
223- time := Time (id )
224- sequence := SequenceNumber (id )
225- machine := MachineID (id )
255+ func ( sf * Sonyflake ) Decompose (id int64 ) map [string ]int64 {
256+ time := sf . timePart (id )
257+ sequence := sf . sequencePart (id )
258+ machine := sf . machinePart (id )
226259 return map [string ]int64 {
227260 "id" : id ,
228261 "time" : time ,
229- "sequence" : int64 ( sequence ) ,
230- "machine" : int64 ( machine ) ,
262+ "sequence" : sequence ,
263+ "machine" : machine ,
231264 }
232265}
266+
267+ func (sf * Sonyflake ) timePart (id int64 ) int64 {
268+ return id >> (sf .bitsSequence + sf .bitsMachine )
269+ }
270+
271+ func (sf * Sonyflake ) sequencePart (id int64 ) int64 {
272+ maskSequence := int64 ((1 << sf .bitsSequence - 1 ) << sf .bitsMachine )
273+ return (id & maskSequence ) >> sf .bitsMachine
274+ }
275+
276+ func (sf * Sonyflake ) machinePart (id int64 ) int64 {
277+ maskMachine := int64 (1 << sf .bitsMachine - 1 )
278+ return id & maskMachine
279+ }
0 commit comments