package module
Version: v0.0.0-...-815e8c3 Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2023 License: EPL-1.0 Imports: 9 Imported by: 3



This is a Go implementation of the Maelstrom Node. This provides basic message handling, an event loop, & a client interface to the key/value store. It's a good starting point for implementing a Maelstrom node as it helps to avoid a lot of boilerplate.


Binaries run by maelstrom need to be referenced by absolute or relative path. The easiest way to use Go with Maelstrom is to go install and then specify the relative path to the --bin flag:

$ cd /path/to/maelstrom-echo
$ go install .
$ maelstrom test --bin ~/go/bin/maelstrom-echo ...




View Source
const (
	LinKV = "lin-kv"
	SeqKV = "seq-kv"
	LWWKV = "lww-kv"

Types of key/value stores.

View Source
const (
	Timeout                = 0
	NotSupported           = 10
	TemporarilyUnavailable = 11
	MalformedRequest       = 12
	Crash                  = 13
	Abort                  = 14
	KeyDoesNotExist        = 20
	KeyAlreadyExists       = 21
	PreconditionFailed     = 22
	TxnConflict            = 30

RPC error code constants.


This section is empty.


func ErrorCode

func ErrorCode(err error) int

ErrorCode returns the error code from err. Returns -1 if err does not have an *RPCError.

func ErrorCodeText

func ErrorCodeText(code int) string

ErrorCodeText returns the text representation of an error code.


type HandlerFunc

type HandlerFunc func(msg Message) error

HandlerFunc is the function signature for a message handler.

type InitMessageBody

type InitMessageBody struct {
	NodeID  string   `json:"node_id,omitempty"`
	NodeIDs []string `json:"node_ids,omitempty"`

InitMessageBody represents the message body for the "init" message.

type KV

type KV struct {
	// contains filtered or unexported fields

KV represents a client to the key/value store service.

func NewKV

func NewKV(typ string, node *Node) *KV

NewKV returns a new instance a KV client for a node.

func NewLWWKV

func NewLWWKV(node *Node) *KV

NewLWWKV returns a client to the last-write-wins key/value store.

func NewLinKV

func NewLinKV(node *Node) *KV

NewLinKV returns a client to the linearizable key/value store.

func NewSeqKV

func NewSeqKV(node *Node) *KV

NewSeqKV returns a client to the sequential key/value store.

func (*KV) CompareAndSwap

func (kv *KV) CompareAndSwap(ctx context.Context, key string, from, to any, createIfNotExists bool) error

CompareAndSwap updates the value for a key if its current value matches the previous value. Creates the key if createIfNotExists is true.

Returns an *RPCError with a code of PreconditionFailed if the previous value does not match. Return a code of KeyDoesNotExist if the key did not exist.

func (*KV) Read

func (kv *KV) Read(ctx context.Context, key string) (any, error)

Read returns the value for a given key in the key/value store. Returns an *RPCError error with a KeyDoesNotExist code if the key does not exist.

func (*KV) ReadInt

func (kv *KV) ReadInt(ctx context.Context, key string) (int, error)

ReadInt reads the value of a key in the key/value store as an int.

func (*KV) ReadInto

func (kv *KV) ReadInto(ctx context.Context, key string, v any) error

ReadInto reads the value of a key in the key/value store and store it in the value pointed by v. Returns an *RPCError error with a KeyDoesNotExist code if the key does not exist.

func (*KV) Write

func (kv *KV) Write(ctx context.Context, key string, value any) error

Write overwrites the value for a given key in the key/value store.

type Message

type Message struct {
	Src  string          `json:"src,omitempty"`
	Dest string          `json:"dest,omitempty"`
	Body json.RawMessage `json:"body,omitempty"`

Message represents a message sent from Src node to Dest node. The body is stored as unparsed JSON so the handler can parse it itself.

func (*Message) RPCError

func (m *Message) RPCError() *RPCError

RPCError returns the RPC error from the message body. Returns a malformed body as a generic crash error.

func (*Message) Type

func (m *Message) Type() string

Type returns the "type" field from the message body. Returns blank string if field does not exist or body is malformed.

type MessageBody

type MessageBody struct {
	// Message type.
	Type string `json:"type,omitempty"`

	// Optional. Message identifier that is unique to the source node.
	MsgID int `json:"msg_id,omitempty"`

	// Optional. For request/response, the msg_id of the request.
	InReplyTo int `json:"in_reply_to,omitempty"`

	// Error code, if an error occurred.
	Code int `json:"code,omitempty"`

	// Error message, if an error occurred.
	Text string `json:"text,omitempty"`

MessageBody represents the reserved keys for a message body.

type Node

type Node struct {

	// Stdin is for reading messages in from the Maelstrom network.
	Stdin io.Reader

	// Stdout is for writing messages out to the Maelstrom network.
	Stdout io.Writer
	// contains filtered or unexported fields

Node represents a single node in the network.

func NewNode

func NewNode() *Node

NewNode returns a new instance of Node connected to STDIN/STDOUT.

func (*Node) Handle

func (n *Node) Handle(typ string, fn HandlerFunc)

Handle registers a message handler for a given message type. Will panic if registering multiple handlers for the same message type.

func (*Node) ID

func (n *Node) ID() string

ID returns the identifier for this node. Only valid after "init" message has been received.

func (*Node) Init

func (n *Node) Init(id string, nodeIDs []string)

Init is used for initializing the node. This is normally called after receiving an "init" message but it can also be called manually when initializing unit tests.

func (*Node) NodeIDs

func (n *Node) NodeIDs() []string

NodeIDs returns a list of all node IDs in the cluster. This list include the local node ID and is the same order across all nodes. Only valid after "init" message has been received.

func (*Node) RPC

func (n *Node) RPC(dest string, body any, handler HandlerFunc) error

RPC sends an async RPC request. Handler invoked when response message received.

func (*Node) Reply

func (n *Node) Reply(req Message, body any) error

Reply replies to a request with a response body.

func (*Node) Run

func (n *Node) Run() error

Run executes the main event handling loop. It reads in messages from STDIN and delegates them to the appropriate registered handler. This should be the last function executed by main().

func (*Node) Send

func (n *Node) Send(dest string, body any) error

Send sends a message body to a given destination node.

func (*Node) SyncRPC

func (n *Node) SyncRPC(ctx context.Context, dest string, body any) (Message, error)

SyncRPC sends a synchronous RPC request. Returns the response message. RPC errors in the message body are converted to *RPCError and are returned.

type RPCError

type RPCError struct {
	Code int
	Text string

RPCError represents a Maelstrom RPC error.

func NewRPCError

func NewRPCError(code int, text string) *RPCError

NewRPCError returns a new instance of RPCError.

func (*RPCError) Error

func (e *RPCError) Error() string

Error returns a string-formatted error message.

func (*RPCError) MarshalJSON

func (e *RPCError) MarshalJSON() ([]byte, error)

MarshalJSON marshals the error into JSON format.


Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL