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.
| method | request | response | description |
|---|---|---|---|
/phalanx.Consensus/AppendEntries | AppendEntriesRequest | AppendEntriesResponse | log replication + heartbeats |
/phalanx.Consensus/RequestVote | RequestVoteRequest | RequestVoteResponse | leader 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.
{
"data": "<base64-encoded fsm.Command>"
}{
"op": "SET", // or "DELETE"
"key": "mykey",
"value": "myvalue" // omitted for DELETE
}{
"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.
{
"key": "mykey"
}{
"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.
| metric | type | description |
|---|---|---|
messages_sent_total | counter | total raft messages dispatched |
election_count | counter | elections initiated |
last_commit_index | gauge | highest committed log index |
proposals_total | counter | client proposals received |
reads_total | counter | client reads served |
applied_index | gauge | highest index applied to FSM |
current_state | string | FOLLOWER / 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.