propose
Proposes command for replication and suspends until a quorum commits it.
Returns the committed LogEntry (which carries the assigned LogEntry.index and LogEntry.term).
May be called from any node in the cluster (Raft §8):
The leader appends the entry directly.
Every other role (Follower, Candidate, Learner) forwards the command to the current leader and suspends until the leader commits it. The committed entry then replicates back to the calling node through the normal AppendEntries path.
If no leader is known yet (during an election), the call waits, cancellably, until a leader is elected and then forwards.
Cancellation is best-effort. A forward that is still queued when the caller cancels is guaranteed not to be sent. However, a command already forwarded to — or appended by — the leader may still commit even if the caller cancels; Raft does not support revocation of in-flight proposals.
A forwarded proposal relies on caller-side timeout for a leader crash. If the leader a proposal was forwarded to steps down, its rejection surfaces here as LeadershipLostException (retry below). But if that leader crashes, no rejection is ever delivered, so this call suspends until the caller cancels it — the library does not spontaneously fail such a proposal. Wrap propose in your own timeout and retry against the next leader; use the requestId overload so the retry is exactly-once-safe. (This is the standard distributed-propose contract: eventual completion of a forwarded proposal is a caller timeout+retry responsibility, not a library guarantee.)
Throws
if a forwarded proposal is rejected by the target leader (e.g. the leader stepped down); the caller may retry on the new leader.
only in terminal cases: the node is closed, or the leader is rejecting proposals because a leadership transfer is in flight.
if command exceeds the transport's published payload budget less an envelope reserve (#2069). Raised on the calling coroutine before the command reaches the log — nothing was appended and no client serial was burned, so a retry with a smaller command is safe. A transport that publishes no budget never raises it.
Proposes command with a caller-pinned requestId (Raft §8 client serial) under this node's clientId, then suspends until a quorum commits it (same semantics as propose).
A durable client replays the same requestId on a post-crash retry to get exactly-once across the crash: the proposer stamps DedupKey(clientId, requestId) onto the entry, it rides the forward hop unchanged, and the consumer's dedup table (ClientSessionTable) skips a serial it has already applied. The auto-serial propose form draws the next monotonic serial itself.