2 Commits

Author SHA1 Message Date
Yoshiyuki Mineo
774342570a Add Compose method (#71) 2025-05-07 13:17:30 +09:00
Yoshiyuki Mineo
59c47aeab1 Fix lint errors (#70) 2025-05-05 19:51:28 +09:00
11 changed files with 133 additions and 45 deletions

View File

@@ -5,12 +5,14 @@ on:
paths-ignore:
- README.md
- .github/workflows/test-v2.yml
- 'v2/**'
- v2/**
pull_request:
paths-ignore:
- README.md
- .github/workflows/test-v2.yml
- 'v2/**'
- v2/**
permissions: read-all
jobs:
test-v1:
@@ -30,7 +32,7 @@ jobs:
uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: ${{matrix.go-version}}

View File

@@ -5,12 +5,14 @@ on:
paths:
- README.md
- .github/workflows/test-v2.yml
- 'v2/**'
- v2/**
pull_request:
paths:
- README.md
- .github/workflows/test-v2.yml
- 'v2/**'
- v2/**
permissions: read-all
jobs:
test-v2:

2
.gitignore vendored
View File

@@ -1,2 +1,4 @@
example/example
example/sonyflake_server
v2/example/example
v2/example/sonyflake_server

View File

@@ -1,6 +1,9 @@
FROM ubuntu:14.04
ADD ./sonyflake_server /
ENTRYPOINT ["/sonyflake_server"]
COPY ./sonyflake_server /sonyflake_server
RUN useradd -m sonyflake
USER sonyflake
ENTRYPOINT ["/sonyflake_server"]
EXPOSE 8080

View File

@@ -1,21 +1,19 @@
Example
=======
# Example
This example runs Sonyflake on AWS Elastic Beanstalk.
Setup
-----
## Setup
1. Build the cross compiler for linux/amd64 if using other platforms.
```
cd $GOROOT/src && GOOS=linux GOARCH=amd64 ./make.bash
```
```bash
cd $GOROOT/src && GOOS=linux GOARCH=amd64 ./make.bash
```
2. Build sonyflake_server in the example directory.
```
./linux64_build.sh
```
```bash
./linux64_build.sh
```
3. Upload the example directory to AWS Elastic Beanstalk.

View File

@@ -1,6 +1,9 @@
FROM ubuntu:24.04
ADD ./sonyflake_server /
ENTRYPOINT ["/sonyflake_server"]
COPY ./sonyflake_server /sonyflake_server
RUN useradd -m sonyflake
USER sonyflake
ENTRYPOINT ["/sonyflake_server"]
EXPOSE 8080

View File

@@ -1,21 +1,19 @@
Example
=======
# Example
This example runs Sonyflake on AWS Elastic Beanstalk.
Setup
-----
## Setup
1. Build the cross compiler for linux/amd64 if using other platforms.
```
cd $GOROOT/src && GOOS=linux GOARCH=amd64 ./make.bash
```
```bash
cd $GOROOT/src && GOOS=linux GOARCH=amd64 ./make.bash
```
2. Build sonyflake_server in the example directory.
```
./linux64_build.sh
```
```bash
./linux64_build.sh
```
3. Upload the example directory to AWS Elastic Beanstalk.

View File

@@ -247,10 +247,22 @@ func lower16BitPrivateIP(interfaceAddrs types.InterfaceAddrs) (int, error) {
return int(ip[2])<<8 + int(ip[3]), nil
}
// ToTime returns the time when the given ID was generated.
func (sf *Sonyflake) ToTime(id int64) time.Time {
return time.Unix(0, (sf.startTime+sf.timePart(id))*sf.timeUnit)
}
// Compose creates a Sonyflake ID from its components.
// 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 {
elapsedTime := sf.toInternalTime(t.UTC()) - sf.startTime
return elapsedTime<<(sf.bitsSequence+sf.bitsMachine) |
int64(sequence)<<sf.bitsMachine |
int64(machineID)
}
// Decompose returns a set of Sonyflake ID parts.
func (sf *Sonyflake) Decompose(id int64) map[string]int64 {
time := sf.timePart(id)

View File

@@ -253,22 +253,6 @@ func TestNextID_ReturnsError(t *testing.T) {
}
}
func TestToTime(t *testing.T) {
start := time.Now()
sf := newSonyflake(t, Settings{
TimeUnit: time.Millisecond,
StartTime: start,
})
id := nextID(t, sf)
tm := sf.ToTime(id)
diff := tm.Sub(start)
if diff < 0 || diff >= time.Duration(sf.timeUnit) {
t.Errorf("unexpected time: %v", tm)
}
}
func TestPrivateIPv4(t *testing.T) {
testCases := []struct {
description string
@@ -351,3 +335,87 @@ func TestLower16BitPrivateIP(t *testing.T) {
})
}
}
func TestToTime(t *testing.T) {
start := time.Now()
sf := newSonyflake(t, Settings{
TimeUnit: time.Millisecond,
StartTime: start,
})
id := nextID(t, sf)
tm := sf.ToTime(id)
diff := tm.Sub(start)
if diff < 0 || diff >= time.Duration(sf.timeUnit) {
t.Errorf("unexpected time: %v", tm)
}
}
func TestComposeAndDecompose(t *testing.T) {
now := time.Now()
sf := newSonyflake(t, Settings{
TimeUnit: time.Millisecond,
StartTime: now,
})
testCases := []struct {
name string
time time.Time
sequence int
machineID int
}{
{
name: "zero values",
time: now,
sequence: 0,
machineID: 0,
},
{
name: "max sequence",
time: now,
sequence: 1<<sf.bitsSequence - 1,
machineID: 0,
},
{
name: "max machine id",
time: now,
sequence: 0,
machineID: 1<<sf.bitsMachine - 1,
},
{
name: "future time",
time: now.Add(time.Hour),
sequence: 0,
machineID: 0,
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
id := sf.Compose(tc.time, tc.sequence, tc.machineID)
parts := sf.Decompose(id)
// Verify time part
expectedTime := sf.toInternalTime(tc.time.UTC()) - sf.startTime
if parts["time"] != expectedTime {
t.Errorf("time mismatch: got %d, want %d", parts["time"], expectedTime)
}
// Verify sequence part
if parts["sequence"] != int64(tc.sequence) {
t.Errorf("sequence mismatch: got %d, want %d", parts["sequence"], tc.sequence)
}
// Verify machine id part
if parts["machine"] != int64(tc.machineID) {
t.Errorf("machine id mismatch: got %d, want %d", parts["machine"], tc.machineID)
}
// Verify id part
if parts["id"] != id {
t.Errorf("id mismatch: got %d, want %d", parts["id"], id)
}
})
}
}