Files
multica/server/cmd/server
Xichang(Seacen) Zhao ccd312c5e2 MUL-7005 fix(wecom): settle a relayed reply's outcome once, after its last offer (#7953)
A relayed reply used to be counted once per delivery attempt: a reply that
failed before the wire and was re-offered recorded a drop on every offer, and
one that later succeeded was counted delivered as well. The outcome is now
recorded once, after the last offer, by the single owner that can know it.

Settling it once takes an at-most-once claim that survives every partial
failure the store can produce:

- Claims are token-fenced through Lua compare-and-act, so a command the client
  re-sends after a lost response can never act on a claim a later owner holds.
- An error from Release or Settle means the outcome is UNKNOWN, never "did not
  happen". Release is resolved by the next offer's Claim; Settle has no later
  offer to resolve it, so it is retried — bounded, and idempotent.
- The publisher's end-of-grace Resolve fences a claim nobody settled, so a
  holder that comes back records nothing and the reply keeps one record.
- outcomeGrace covers both store round trips per offer, so it cannot expire
  while the chain is still running.

The retry lives inside the shutdown budget. Release and Settle still ignore
plain cancellation — a frame already in the user's chat has to have its claim
settled — but they inherit a bounding deadline, and the loop opens no new
attempt once one has passed. Those deadlines reach the wire only because the
claim store gets its own Redis client: go-redis discards context deadlines
unless ContextTimeoutEnabled is set, and setting it on the shared relay client
would change the timeout behaviour of every realtime publish.

One boundary is deliberately accepted and now stated in the code, the log and a
test: a store that keeps losing settle responses can leave a delivered reply
with no outcome recorded. Recording it instead would double the far more common
case. That is a monitoring gap under a failing store, not a reply the user did
not get.
2026-09-09 16:53:08 +08:00
..