blip 0.3.0

A crate for writing fast and highly resilient in-process gRPC service meshes.
Documentation
// Copyright 2020 nytopop (Eric Izoita)
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.
syntax = "proto2";

package blip;

// The interface that a node running the blip protocol should expose.
service Membership {
	rpc PreJoin(PreJoinReq) returns (PreJoinResp);

	rpc Join(JoinReq) returns (JoinResp);

	rpc BatchedAlert(BatchedAlertReq) returns (Ack);

	rpc FastAccepted(FastAcceptedReq) returns (Ack);

	rpc Prepare(PrepareReq) returns (Ack);

	rpc Promise(PromiseReq) returns (Ack);

	rpc Accept(AcceptReq) returns (Ack);

	rpc Accepted(AcceptedReq) returns (Ack);

	rpc Broadcast(BroadcastReq) returns (Ack);

	rpc Probe(Ack) returns (Ack);
}

// A listening address.
message Endpoint {
	// An ip address in binary form. Exactly 4 or 16 bytes long.
	required bytes host = 1;
	// Port number. Is 0xffff or smaller.
	required uint32 port = 2;
	// Whether tls is enabled.
	required bool tls = 3;
}

// A 128 bit unique identifier.
message NodeId {
	// The high bits.
	required uint64 high = 1;
	// The low bits.
	required uint64 low = 2;
}

// Metadata exposed by a node during the join protocol.
//
// Should be populated sparingly, as it will be propagated by various messages
// and stored in each node's configuration.
message Metadata {
	// Any keys exposed by the node.
	map<string, bytes> keys = 1;
}

// A listening address, as well as any metadata associated with the node that
// address refers to.
message NodeMetadata {
	// A listening address.
	required Endpoint node = 1;
	// The node's metadata.
	required Metadata meta = 2;
}

// An acknowledgement of receipt, used as a response for rpcs that don't convey
// any information other than that they succeeded.
message Ack {}

// A phase 1 join request, sent by nodes seeking to join a cluster.
message PreJoinReq {
	// The address with which the sender expects to be referred to.
	required Endpoint sender = 1;
	// A unique uuid for the sender.
	required NodeId uuid = 2;
}

// A phase 1 join response.
message PreJoinResp {
	// The address with which the sender expects to be referred to.
	required Endpoint sender = 1;
	// The configuration that will be joined.
	required uint64 conf_id = 2;
	// A list of observers to contact for phase 2 of the join protocol.
	repeated Endpoint contact = 3;
}

// A phase 2 join request, sent to each observer in a phase 1 join response.
message JoinReq {
	// The address with which the sender expects to be referred to.
	required Endpoint sender = 1;
	// The ring number sender expects us to observe them at.
	required uint64 ring = 2;
	// A unique uuid for the sender.
	required NodeId uuid = 3;
	// The configuration sender is trying to join.
	required uint64 conf_id = 4;
	// Any metadata that sender wants to expose.
	required Metadata meta = 5;
}

// A phase 2 join response.
message JoinResp {
	// The address with which the sender expects to be referred to.
	required Endpoint sender = 1;
	// The updated configuration (which requester is now part of).
	required uint64 conf_id = 2;
	// All nodes/metadata in the new configuration.
	repeated NodeMetadata nodes = 3;
	// All uuids in the new configuration.
	repeated NodeId uuids = 4;
}

// A batch of edge alerts.
message BatchedAlertReq {
	// The address with which the sender expects to be referred to.
	required Endpoint sender = 1;
	// The configuration this batch refers to (which sender is a part of).
	required uint64 conf_id = 2;
	// The edge alerts.
	repeated Edge edges = 3;
}

// An alert about some edge between an observer and subject changing state.
message Edge {
	// The subject node this alert refers to.
	required Endpoint node = 1;
	// The ring on which sender is the observer of node.
	required uint64 ring = 2;
	// Additional information about node. If set, this alert indicates that
	// node is attempting to join the cluster. Otherwise, somebody is trying
	// to eject node from the cluster.
	optional Join join = 3;
}

// Additional information about a joining node.
message Join {
	// The node's unique identifier.
	required NodeId uuid = 1;
	// The node's exposed metadata.
	required Metadata meta = 2;
}

message FastAcceptedReq {
	required Endpoint sender = 1;
	required uint64 conf_id = 2;
	repeated Endpoint nodes = 3;
}

message Rank {
	required uint32 round = 1;
	required uint64 node_idx = 2;
}

message PrepareReq {
	required Endpoint sender = 1;
	required uint64 conf_id = 2;
	required Rank rank = 3;
}

message PromiseReq {
	required Endpoint sender = 1;
	required uint64 conf_id = 2;
	required Rank rnd = 3;
	required Rank vrnd = 4;
	repeated Endpoint vval = 5;
}

message AcceptReq {
	required Endpoint sender = 1;
	required uint64 conf_id = 2;
	required Rank rnd = 3;
	repeated Endpoint vval = 4;
}

message AcceptedReq {
	required Endpoint sender = 1;
	required uint64 conf_id = 2;
	required Rank rnd = 3;
	repeated Endpoint nodes = 4;
}

// A request to broadcast some message.
message BroadcastReq {
	// Unix timestamp generated by the message originator, in seconds since
	// the unix epoch.
	required uint64 unix = 1;
	// A unique identifier for the message. Receivers of broadcast requests
	// should ignore any requests if this id has already been seen.
	required uint64 uniq = 2;
	// The message to be broadcast.
	oneof broadcasted {
		BatchedAlertReq BatchedAlert = 3;
		FastAcceptedReq FastAccepted = 4;
		PrepareReq Prepare = 5;
		PromiseReq Promise = 6;
		AcceptReq Accept = 7;
		AcceptedReq Accepted = 8;
	}
}