Skip to content

Commit fe28177

Browse files
Add Compose method and corresponding tests
* Implemented the Compose function to create a Sonyflake ID from its components, including validation for start time, sequence, and machine ID. * Added a new test, TestCompose, to verify the functionality of the Compose method, ensuring correct decomposition of generated IDs. * Introduced a new error for invalid sequence numbers to enhance error handling in the Sonyflake package.
1 parent 5c401f9 commit fe28177

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

sonyflake.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ var (
5757
ErrNoPrivateAddress = errors.New("no private ip address")
5858
ErrOverTimeLimit = errors.New("over the time limit")
5959
ErrInvalidMachineID = errors.New("invalid machine id")
60+
ErrInvalidSequence = errors.New("invalid sequence number")
6061
)
6162

6263
var defaultInterfaceAddrs = net.InterfaceAddrs
@@ -213,6 +214,25 @@ func MachineID(id uint64) uint64 {
213214
return id & maskMachineID
214215
}
215216

217+
// Compose creates a Sonyflake ID from its parts.
218+
func Compose(sf *Sonyflake, t time.Time, sequence uint16, machineID uint16) (uint64, error) {
219+
elapsedTime := toSonyflakeTime(t.UTC()) - sf.startTime
220+
if elapsedTime < 0 {
221+
return 0, ErrStartTimeAhead
222+
}
223+
if elapsedTime >= 1<<BitLenTime {
224+
return 0, ErrOverTimeLimit
225+
}
226+
227+
if sequence >= 1<<BitLenSequence {
228+
return 0, ErrInvalidSequence
229+
}
230+
231+
return uint64(elapsedTime)<<(BitLenSequence+BitLenMachineID) |
232+
uint64(sequence)<<BitLenMachineID |
233+
uint64(machineID), nil
234+
}
235+
216236
// Decompose returns a set of Sonyflake ID parts.
217237
func Decompose(id uint64) map[string]uint64 {
218238
msb := id >> 63

sonyflake_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,3 +312,36 @@ func TestSonyflakeTimeUnit(t *testing.T) {
312312
t.Errorf("unexpected time unit")
313313
}
314314
}
315+
316+
func TestCompose(t *testing.T) {
317+
var st Settings
318+
st.StartTime = time.Date(2023, 1, 1, 0, 0, 0, 0, time.UTC)
319+
sf, err := New(st)
320+
if err != nil {
321+
t.Fatal(err)
322+
}
323+
324+
now := time.Now()
325+
sequence := uint16(123)
326+
machineID := uint16(456)
327+
328+
id, err := Compose(sf, now, sequence, machineID)
329+
if err != nil {
330+
t.Fatal(err)
331+
}
332+
333+
parts := Decompose(id)
334+
335+
actualTime := toSonyflakeTime(now) - toSonyflakeTime(st.StartTime)
336+
if parts["time"] != uint64(actualTime) {
337+
t.Errorf("unexpected time: %d", parts["time"])
338+
}
339+
340+
if parts["sequence"] != uint64(sequence) {
341+
t.Errorf("unexpected sequence: %d", parts["sequence"])
342+
}
343+
344+
if parts["machine-id"] != uint64(machineID) {
345+
t.Errorf("unexpected machine id: %d", parts["machine-id"])
346+
}
347+
}

0 commit comments

Comments
 (0)