mirror of
https://github.com/sony/sonyflake.git
synced 2026-01-08 12:01:09 +00:00
Compare commits
4 Commits
v2.1.0
...
0cdef9e4fe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0cdef9e4fe | ||
|
|
114716564a | ||
|
|
2343cac676 | ||
|
|
5347433c8c |
@@ -74,8 +74,9 @@ var (
|
||||
ErrInvalidBitsSequence = errors.New("invalid bit length for sequence number")
|
||||
ErrInvalidBitsMachineID = errors.New("invalid bit length for machine id")
|
||||
ErrInvalidTimeUnit = errors.New("invalid time unit")
|
||||
ErrInvalidSequence = errors.New("invalid sequence number")
|
||||
ErrInvalidMachineID = errors.New("invalid machine id")
|
||||
ErrStartTimeAhead = errors.New("start time is ahead of now")
|
||||
ErrStartTimeAhead = errors.New("start time is ahead")
|
||||
ErrOverTimeLimit = errors.New("over the time limit")
|
||||
ErrNoPrivateAddress = errors.New("no private ip address")
|
||||
)
|
||||
@@ -157,6 +158,10 @@ func New(st Settings) (*Sonyflake, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if sf.machine < 0 || sf.machine >= 1<<sf.bitsMachine {
|
||||
return nil, ErrInvalidMachineID
|
||||
}
|
||||
|
||||
if st.CheckMachineID != nil && !st.CheckMachineID(sf.machine) {
|
||||
return nil, ErrInvalidMachineID
|
||||
}
|
||||
@@ -256,11 +261,26 @@ func (sf *Sonyflake) ToTime(id int64) time.Time {
|
||||
// The time parameter should be the time when the ID was generated.
|
||||
// The sequence parameter should be between 0 and 2^BitsSequence-1 (inclusive).
|
||||
// The machineID parameter should be between 0 and 2^BitsMachineID-1 (inclusive).
|
||||
func (sf *Sonyflake) Compose(t time.Time, sequence, machineID int) int64 {
|
||||
func (sf *Sonyflake) Compose(t time.Time, sequence, machineID int) (int64, error) {
|
||||
elapsedTime := sf.toInternalTime(t.UTC()) - sf.startTime
|
||||
if elapsedTime < 0 {
|
||||
return 0, ErrStartTimeAhead
|
||||
}
|
||||
if elapsedTime >= 1<<sf.bitsTime {
|
||||
return 0, ErrOverTimeLimit
|
||||
}
|
||||
|
||||
if sequence < 0 || sequence >= 1<<sf.bitsSequence {
|
||||
return 0, ErrInvalidSequence
|
||||
}
|
||||
|
||||
if machineID < 0 || machineID >= 1<<sf.bitsMachine {
|
||||
return 0, ErrInvalidMachineID
|
||||
}
|
||||
|
||||
return elapsedTime<<(sf.bitsSequence+sf.bitsMachine) |
|
||||
int64(sequence)<<sf.bitsMachine |
|
||||
int64(machineID)
|
||||
int64(machineID), nil
|
||||
}
|
||||
|
||||
// Decompose returns a set of Sonyflake ID parts.
|
||||
|
||||
@@ -65,6 +65,24 @@ func TestNew(t *testing.T) {
|
||||
},
|
||||
err: errGetMachineID,
|
||||
},
|
||||
{
|
||||
name: "too large machine id",
|
||||
settings: Settings{
|
||||
MachineID: func() (int, error) {
|
||||
return 1 << defaultBitsMachine, nil
|
||||
},
|
||||
},
|
||||
err: ErrInvalidMachineID,
|
||||
},
|
||||
{
|
||||
name: "negative machine id",
|
||||
settings: Settings{
|
||||
MachineID: func() (int, error) {
|
||||
return -1, nil
|
||||
},
|
||||
},
|
||||
err: ErrInvalidMachineID,
|
||||
},
|
||||
{
|
||||
name: "invalid machine id",
|
||||
settings: Settings{
|
||||
@@ -239,10 +257,11 @@ func pseudoSleep(sf *Sonyflake, period time.Duration) {
|
||||
sf.startTime -= int64(period) / sf.timeUnit
|
||||
}
|
||||
|
||||
const year = time.Duration(365*24) * time.Hour
|
||||
|
||||
func TestNextID_ReturnsError(t *testing.T) {
|
||||
sf := newSonyflake(t, Settings{StartTime: time.Now()})
|
||||
|
||||
year := time.Duration(365*24) * time.Hour
|
||||
pseudoSleep(sf, time.Duration(174)*year)
|
||||
nextID(t, sf)
|
||||
|
||||
@@ -339,7 +358,7 @@ func TestLower16BitPrivateIP(t *testing.T) {
|
||||
func TestToTime(t *testing.T) {
|
||||
start := time.Now()
|
||||
sf := newSonyflake(t, Settings{
|
||||
TimeUnit: time.Millisecond,
|
||||
TimeUnit: 100 * time.Millisecond,
|
||||
StartTime: start,
|
||||
})
|
||||
|
||||
@@ -347,7 +366,7 @@ func TestToTime(t *testing.T) {
|
||||
|
||||
tm := sf.ToTime(id)
|
||||
diff := tm.Sub(start)
|
||||
if diff < 0 || diff >= time.Duration(sf.timeUnit) {
|
||||
if diff < 0 || diff > time.Duration(sf.timeUnit) {
|
||||
t.Errorf("unexpected time: %v", tm)
|
||||
}
|
||||
}
|
||||
@@ -393,7 +412,11 @@ func TestComposeAndDecompose(t *testing.T) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
id := sf.Compose(tc.time, tc.sequence, tc.machineID)
|
||||
id, err := sf.Compose(tc.time, tc.sequence, tc.machineID)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
parts := sf.Decompose(id)
|
||||
|
||||
// Verify time part
|
||||
@@ -419,3 +442,54 @@ func TestComposeAndDecompose(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCompose_ReturnsError(t *testing.T) {
|
||||
start := time.Now()
|
||||
sf := newSonyflake(t, Settings{StartTime: start})
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
time time.Time
|
||||
sequence int
|
||||
machineID int
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "start time ahead",
|
||||
time: start.Add(-time.Second),
|
||||
sequence: 0,
|
||||
machineID: 0,
|
||||
err: ErrStartTimeAhead,
|
||||
},
|
||||
{
|
||||
name: "over time limit",
|
||||
time: start.Add(time.Duration(175) * year),
|
||||
sequence: 0,
|
||||
machineID: 0,
|
||||
err: ErrOverTimeLimit,
|
||||
},
|
||||
{
|
||||
name: "invalid sequence",
|
||||
time: start,
|
||||
sequence: 1 << sf.bitsSequence,
|
||||
machineID: 0,
|
||||
err: ErrInvalidSequence,
|
||||
},
|
||||
{
|
||||
name: "invalid machine id",
|
||||
time: start,
|
||||
sequence: 0,
|
||||
machineID: 1 << sf.bitsMachine,
|
||||
err: ErrInvalidMachineID,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := sf.Compose(tc.time, tc.sequence, tc.machineID)
|
||||
if !errors.Is(err, tc.err) {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user