-
Notifications
You must be signed in to change notification settings - Fork 2
/
unique_ids.go
75 lines (61 loc) · 1.33 KB
/
unique_ids.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package main
import (
"encoding/json"
"log"
"math/rand"
"os"
"sync"
"sync/atomic"
"time"
maelstrom "github.com/jepsen-io/maelstrom/demo/go"
)
type SeqCounter struct {
seq atomic.Int64
nodeId uint32
lastTime int64
mu sync.Mutex
}
func main() {
s := rand.NewSource(time.Now().UnixNano())
randId := rand.New(s).Intn(100-1) + 1
counter := &SeqCounter{
seq: atomic.Int64{},
nodeId: uint32(randId),
lastTime: 0,
mu: sync.Mutex{},
}
n := maelstrom.NewNode()
n.Handle("generate", func(msg maelstrom.Message) error {
var body map[string]any
if err := json.Unmarshal(msg.Body, &body); err != nil {
return err
}
body["id"] = generateId(counter)
body["type"] = "generate_ok"
return n.Reply(msg, body)
})
if err := n.Run(); err != nil {
log.Printf("ERROR: %s", err)
os.Exit(1)
}
}
func generateId(counter *SeqCounter) int64 {
ts := getTime(counter)
var id = ts << 22
id = id | int64(counter.nodeId)<<15
next := counter.seq.Add(1)
id = id | (next % 2048)
return id
}
func getTime(counter *SeqCounter) int64 {
counter.mu.Lock()
defer counter.mu.Unlock()
currentTime := time.Now().UnixMilli()
lastTime := counter.lastTime
for currentTime == lastTime {
time.Sleep(time.Millisecond)
currentTime = time.Now().UnixMilli()
}
counter.lastTime = currentTime
return currentTime
}