1
1
package com .gb .didgen .service ;
2
2
3
+ import com .gb .didgen .exception .ClockMovedBackException ;
3
4
import com .gb .didgen .exception .NodeIdOutOfBoundException ;
4
5
import lombok .AllArgsConstructor ;
5
6
import org .springframework .stereotype .Service ;
@@ -17,11 +18,12 @@ public class SnowflakeIdGenerator implements IdGenerator {
17
18
private final int maxSequence = (int ) Math .pow (2 , SEQUENCE_BIT_LEN );
18
19
private final int maxNodeVal = (int ) Math .pow (2 , NODE_ID_BIT_LEN );
19
20
20
- private final long EPOCH = Instant .EPOCH .toEpochMilli ();
21
+ private final long EPOCH_START = Instant .EPOCH .toEpochMilli ();
21
22
22
23
private final int generatingNodeId ;
23
24
private volatile long currentSequence ;
24
- private volatile long lastTimestamp ;
25
+ private final Object lock = new Object ();
26
+ private volatile long lastTimestamp = 0L ;
25
27
26
28
@ PostConstruct
27
29
public void checkNodeIdBounds () throws NodeIdOutOfBoundException {
@@ -31,7 +33,36 @@ public void checkNodeIdBounds() throws NodeIdOutOfBoundException {
31
33
}
32
34
33
35
@ Override
34
- public long generateId () {
35
- return 0 ;
36
+ public long generateId () throws ClockMovedBackException {
37
+ synchronized (lock ) {
38
+ long currentTimeStamp = getTimeStamp ();
39
+ if (currentTimeStamp < lastTimestamp ) {
40
+ throw new ClockMovedBackException ("Clock moved back" );
41
+ }
42
+ if (currentTimeStamp == lastTimestamp ) {
43
+ currentSequence = currentSequence + 1 & maxSequence ;
44
+ if (currentSequence == 0 ) {
45
+ currentTimeStamp = waitNextMillis (currentTimeStamp );
46
+ }
47
+ } else {
48
+ currentSequence = 0 ;
49
+ }
50
+ lastTimestamp = currentTimeStamp ;
51
+ long id = currentTimeStamp << (NODE_ID_BIT_LEN + SEQUENCE_BIT_LEN );
52
+ id |= (generatingNodeId << SEQUENCE_BIT_LEN );
53
+ id |= currentSequence ;
54
+ return id ;
55
+ }
56
+ }
57
+
58
+ private long getTimeStamp () {
59
+ return Instant .now ().toEpochMilli () - EPOCH_START ;
60
+ }
61
+
62
+ private long waitNextMillis (long currentTimeStamp ) {
63
+ while (currentTimeStamp == lastTimestamp ) {
64
+ currentTimeStamp = getTimeStamp ();
65
+ }
66
+ return currentTimeStamp ;
36
67
}
37
68
}
0 commit comments