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! ヽ(‘ー`)ノ