Skip to content

gorums: add the ID alias, Config.Node, and ServerContext.SenderID - #355

Merged
meling merged 4 commits into
masterfrom
feature/165/node-ids
Oct 10, 2026
Merged

meling merged 4 commits into
masterfrom
feature/165/node-ids

Conversation

@meling

@meling meling commented Oct 10, 2026

Copy link
Copy Markdown
Member

Closes #165

Problem

Gorums identifies nodes with plain uint32 values, so signatures do not say what a number means. Applications also kept writing the same two helpers. The decision comment on #165 looked at five systems built on Gorums and found these gaps:

  • There is no lookup by ID. Several applications wrote Config.Node(id) themselves.
  • A handler cannot see who sent a request. Applications put a sender ID in every message, or, like HotStuff, read it from gRPC metadata or the TLS certificate.

#248 tried a generic node ID type parameter. It is closed, because the type parameter would spread to Server, ServerContext, every handler, and every option.

Change

  • gorums.ID is an alias for uint32. It replaces node-ID uint32 in the API, in gorumstest, in the storage example, and in the guides. Its doc comment states the ID rules: 0 is reserved, back-channel clients get IDs from 2^20, servers configured with WithPeers must agree on IDs, and under stream deduplication the lower ID dials. Because it is an alias, code that uses uint32 and protobuf uint32 fields keeps compiling.

  • Config.Node(id) returns the node with the given ID, or nil. Contains, CallContext.Node, and gorumstest.PeerNode now use it.

  • ServerContext.SenderID() returns the ID of the node that sent the request, as this server knows it:

    • a configured peer has its configured ID;
    • a back-channel client has the ID that the server assigned to it;
    • a request on a connection that this server dialed has the dialed node's ID;
    • a request that the server sends to itself has the server's own ID.

    Regular clients and unknown IDs report 0, because Gorums already gives them untracked channels with ID 0. The sender is the last hop, and the server does not authenticate it; feat: stronger peer identity guarantees #325 covers authentication.

    Every channel already holds its peer's ID. The internal stream.RequestHandler.HandleRequest now takes it as a senderID parameter.

  • User guide: a new "Node IDs" section covers the ID rules, choosing IDs, mapping application IDs such as strings to node IDs, and finding the sender.

The public changes are additions. The alias is the same type as uint32, so no existing call site breaks.

Keeping the NodeAddress value on the node, for a reverse mapping or per-node keys, is deferred to #325.

Testing

  • TestConfigNode covers present, absent, unsorted, zero, empty, and nil configurations.
  • TestServerSenderID covers six paths: known peers and self, stream deduplication, regular client, unknown peer ID, back-channel client, and the client side of a back-channel call. When the stream or local channel passes 0 instead of its ID, the subtests fail.
  • go test ./... passes in the root and examples modules, also with -tags=integration. -race passes for the root, internal/conn, internal/stream, internal/impl, and gorumstest packages. benchkit builds and vets unchanged.
  • Each commit builds and passes the affected package tests on its own.

Node IDs were plain uint32 values in the API, so signatures did not
say what a number meant, and the rules for IDs had no single home.
Add the alias ID = uint32, defined in internal/stream and re-exported
through internal/conn and the gorums package, and use it wherever a
uint32 denotes a node ID. The gorums.ID doc comment states the rules:
0 is reserved, back-channel clients get IDs from 2^20, servers
configured with WithPeers must agree on IDs, and under stream
deduplication the lower ID dials.

Because ID is an alias, code that uses uint32 and protobuf uint32
fields keeps working without conversion.
Applications that hold a node ID, from a response or a sender, had
to scan the configuration to find the node. Add Config.Node, which
returns the node with the given ID or nil. Contains, CallContext.Node,
and gorumstest.PeerNode now use it, so the lookup exists once.
A handler could not tell which node sent a request, so applications
put a sender ID in their messages or read gRPC metadata themselves.
Every channel already knows its peer's ID, so pass it to
stream.RequestHandler.HandleRequest and expose it as
ServerContext.SenderID.

The ID is the sender as this server knows it: a configured peer's
ID, a back-channel client's assigned ID, the dialed node's ID on a
connection this server dialed, or the server's own ID for local
calls. Regular clients and unknown IDs report 0, because they use
untracked channels with ID 0. The sender is the last hop, and the
server does not authenticate it.
Add a Node IDs section that states the rules for IDs, shows how to
choose IDs and how to map application IDs such as strings to Gorums
IDs, and explains how a handler finds the sender with SenderID and
Config.Node.

Closes #165
Copilot AI balanced review requested due to automatic review settings October 10, 2026 21:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

Sender identity is consistently propagated across channel types with comprehensive tests and documentation.

0 open findings

What changed in this PR

Implements issue #165 by making node identity explicit and available to handlers.

Changes:

  • Adds the gorums.ID alias and updates node-ID APIs.
  • Adds Config.Node and ServerContext.SenderID.
  • Adds sender-path tests and node-ID documentation.
File Description
config.go Exposes ID and updates node configuration APIs.
server.go Propagates and exposes request sender IDs.
server_test.go Tests sender IDs across connection paths.
server_options.go Uses ID for peer configuration.
local_servers.go Uses ID for local server IDs.
internal/​stream/​transport.go Uses ID in transports.
internal/​stream/​session.go Passes sender IDs to handlers.
internal/​stream/​send_queue.go Uses ID in send queues.
internal/​stream/​request.go Defines the stream-layer ID alias.
internal/​stream/​request_test.go Updates handler test adapter.
internal/​stream/​outbound.go Uses ID for outbound channels.
internal/​stream/​local.go Passes local sender IDs.
internal/​stream/​inbound.go Uses ID for inbound channels.
internal/​stream/​channel.go Extends the request-handler contract.
internal/​stream/​channel_test.go Updates handler test implementation.
internal/​impl/​responses.go Keys collected responses by ID.
internal/​impl/​call_context.go Delegates node lookup to Config.Node.
internal/​impl/​call_context_test.go Updates handler test implementation.
internal/​impl/​aliases.go Adds the implementation-layer ID alias.
internal/​conn/​testhelpers.go Uses ID in node test construction.
internal/​conn/​outbound_manager.go Keys outbound lookup by ID.
internal/​conn/​node.go Defines and applies the connection-layer ID alias.
internal/​conn/​node_source.go Uses ID when building configurations.
internal/​conn/​inbound_manager.go Uses ID for peers and dynamic clients.
internal/​conn/​inbound_manager_test.go Updates handler test adapter.
internal/​conn/​errors.go Uses ID in per-node errors.
internal/​conn/​dial_options.go Uses ID for local-node options.
internal/​conn/​config.go Adds node lookup and updates ID APIs.
internal/​conn/​config_test.go Covers node lookup edge cases.
gorumstest/​gorumstest.go Uses Config.Node in PeerNode.
gorumstest/​errors.go Uses gorums.ID for error maps.
examples/​storage/​server.go Adopts gorums.ID in the storage example.
doc/​user-guide.md Documents node-ID rules and sender lookup.
doc/​dev-guide.md Updates architecture diagrams and handler flow.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@meling
meling merged commit 3e93abd into master Oct 10, 2026
4 checks passed
@meling
meling deleted the feature/165/node-ids branch October 10, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: generic datatype for node ID

2 participants