feat(bridge): protocol 6 — an idempotency key, and champ.boss.killed (Phase 11a)
A command carrying an `idempotencyKey` is now executed at most once: a repeat is answered with the original reply rather than re-run. That is the precondition every world verb in Phase 12 is waiting on, and it is what let `uo.broadcast` stop being un-retryable. The gate sits in BridgeBoot's inbound dispatch, not in each handler, so it covers every kind including ones a later protocol adds. A command with no key behaves exactly as it did before, which leaves the admin screens unchanged. Four rules, each a decision rather than an implementation detail: reserve on receipt (so a handler that defers is covered, answering `bridge.busy` to a repeat in flight); a key that has begun is never released, not even when the handler throws; a replay is stamped with the REPEAT's correlation id, because the sidecar's reqId is fresh per call and replaying the original would hang the retry; and the bound is loud, because an evicted key is the guarantee's one hole. `champ.boss.killed` rides along because a bump costs a release, a bundle and an operator update on every shard. It fires from EventSink.CreatureDeath, detected by type so a boss that popped and died inside one sweep is still reported, and it carries the damage table that exists at the death and nowhere else. overlay.toml protocol = 6, in this commit rather than a later one. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -107,7 +107,17 @@ namespace Server.Custom.Bridge
|
||||
/// </summary>
|
||||
public static void Emit(string line)
|
||||
{
|
||||
if (!_running || line == null)
|
||||
if (line == null)
|
||||
return;
|
||||
|
||||
// Protocol 6. While a keyed command's handler runs — Core thread, one at a time — every
|
||||
// line it emits is offered to the recent-key store so the correlated reply can be
|
||||
// replayed to a retry later. Deliberately BEFORE the `_running` check: a reply the link
|
||||
// was too dead to deliver is precisely the one a retry will come back for.
|
||||
if (BridgeIdempotency.Capturing)
|
||||
BridgeIdempotency.Observe(line);
|
||||
|
||||
if (!_running)
|
||||
return;
|
||||
|
||||
// Drop-oldest. Bound first, then enqueue, so the queue can transiently sit one over
|
||||
|
||||
Reference in New Issue
Block a user