PHALANXconsensus engine
v1.0.0

api reference

gRPC services, request/response formats, and the debug HTTP interface.

Phalanx exposes two gRPC services and one HTTP debug endpoint. All gRPC communication uses a JSON codec — no protoc compiler required. Clients in any language can interact with phalanx by sending JSON-encoded payloads over gRPC with the content-subtype: json call option.

consensus service

Internal node-to-node RPCs. Not intended for client use.

methodrequestresponsedescription
/phalanx.Consensus/AppendEntriesAppendEntriesRequestAppendEntriesResponselog replication + heartbeats
/phalanx.Consensus/RequestVoteRequestVoteRequestRequestVoteResponseleader election + pre-vote

kv service

Client-facing RPCs for reading and writing data.

KV.Propose

Submit a mutation (SET or DELETE) to the cluster. The request blocks until the entry is committed to a majority.

request — ProposeRequest
{
  "data": "<base64-encoded fsm.Command>"
}
command format (json inside data)
{
  "op": "SET",       // or "DELETE"
  "key": "mykey",
  "value": "myvalue" // omitted for DELETE
}
response — ProposeResponse
{
  "success": true,
  "leader_addr": "",     // populated on redirect
  "error": ""            // populated on failure
}

error: not leader

If the node receiving the request is not the leader, it returns:

{
  "success": false,
  "leader_addr": "127.0.0.1:9000",
  "error": "not leader"
}

KV.Read

Read a value by key. Linearizable — the leader verifies quorum before responding.

request — ReadRequest
{
  "key": "mykey"
}
response — ReadResponse
{
  "value": "myvalue",
  "found": true,
  "leader_addr": "",
  "error": ""
}

error: lost quorum

{
  "value": "",
  "found": false,
  "error": "leader lost quorum — cannot serve linearizable read"
}

http debug interface

Every node exposes a debug HTTP server (default port 8080).

GET /health

{
  "status": "ok",
  "node": "node-0",
  "state": "LEADER"
}

GET /debug/status

{
  "node_id": "node-0",
  "state": "LEADER",
  "term": 5,
  "leader_id": "node-0",
  "commit_index": 42,
  "applied_index": 42,
  "log_length": 43,
  "peers": ["node-1", "node-2"],
  "kv_size": 15,
  "kv_data": {
    "foo": "bar",
    "config.ttl": "3600"
  },
  "metrics": {
    "messages_sent_total": 1247,
    "election_count": 1,
    "proposals_total": 15,
    "reads_total": 8,
    "applied_index": 42,
    "current_state": "LEADER"
  }
}

metrics

All metrics use atomic.Uint64 for lock-free concurrent access.

metrictypedescription
messages_sent_totalcountertotal raft messages dispatched
election_countcounterelections initiated
last_commit_indexgaugehighest committed log index
proposals_totalcounterclient proposals received
reads_totalcounterclient reads served
applied_indexgaugehighest index applied to FSM
current_statestringFOLLOWER / CANDIDATE / LEADER

grpc codec

Phalanx registers a custom JSON codec with gRPC. Clients must use thejson content subtype:

conn, _ := grpc.Dial(addr,
    grpc.WithTransportCredentials(insecure.NewCredentials()),
    grpc.WithDefaultCallOptions(
        grpc.CallContentSubtype("json"),
    ),
)

// Then invoke directly:
conn.Invoke(ctx, "/phalanx.KV/Propose", req, resp)

this means any language with a gRPC client can interact with phalanx without generating protobuf stubs. just send JSON.