Challenge #2: Unique ID Generation
In this second challenge, we're tasked with writing a "globally-unique ID generation system that runs against Maelstrom's unique-ids
workload. Your service should be totally available, meaning that it can continue to operate even in the face of network partitions."
As with the previous challenge, we'll start by initialising our Go module and filling in our main.go
file.
$ go mod init github.com/nchengyeeshen/generate
$ touch main.go
package main
import (
"encoding/json"
"log"
maelstrom "github.com/jepsen-io/maelstrom/demo/go"
)
func main() {
n := maelstrom.NewNode()
if err := n.Run(); err != nil {
log.Fatal(err)
}
}
The instructions state that "IDs may be of any type--strings, booleans, integers, floats, arrays, etc.". This is great! It means we have the freedom to choose any ID generation scheme we want.
For ID generation schemes, I tend to be a fan of UUIDs. It's commonly used and has a low chance for collisions.
We'll use Google's UUID Go library, github.com/google/uuid
.
package main
import (
"encoding/json"
"log"
"github.com/google/uuid"
maelstrom "github.com/jepsen-io/maelstrom/demo/go"
)
func main() {
n := maelstrom.NewNode()
n.Handle("generate", func(msg maelstrom.Message) error {
var body struct {
Type string `json:"type"`
}
if err := json.Unmarshal(msg.Body, &body); err != nil {
return err
}
return n.Reply(msg, struct {
Type string `json:"type"`
ID string `json:"id"`
}{
Type: "generate_ok",
ID: uuid.NewString(),
})
})
if err := n.Run(); err != nil {
log.Fatal(err)
}
}
uuid.NewString()
generates a new UUIDv4 string.
Let's compile and run this!
go build -o generate . && maelstrom test -w unique-ids --bin ./generate --time-limit 30 --rate 1000 --node-count 3 --availability total --nemesis partition
During the tests, maelstrom
checks for total availability (--availability total
) and induces network partitions (--nemesis partition
).
After all the tests, it looks like we're all good!
Everything looks good! ヽ(‘ー`)ノ