mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-25 22:21:17 +00:00
* fix(mattermost): adopt durable ingress drain at the websocket chokepoint Posted events processed detached from the websocket receive with only a 5-minute in-memory guard; a crash lost the post and reconnect never replays it. Raw posted envelopes now journal durably (event_id = post.id per the upstream Post model, lane per channel_id, one row per post) before handler scheduling; dispatch runs through the core drain with deferred claims through debounce, merged-flush fan-out adoption, gated-turn settlement, and 30d/20k tombstones covering the old 5min/2k guard, which is deleted after its parity test. post_edited stays excluded and cannot be swallowed by posted tombstones. Cold-gap limitation stated: Mattermost cannot replay posts missed while disconnected. Autoreview blocked by codex sandbox network in the build stage; full manual review performed (updated one websocket test asserting the pre-adoption parsed-post contract to the raw-envelope contract). Part of #109657 wave 2. * style(mattermost): keep ingress monitor type internal * fix(mattermost): retry then loudly escalate a failed durable append Landing autoreview caught a real loss path: a durable enqueue failure at the websocket chokepoint was logged and swallowed — the raw envelope discarded, the connection kept running against a broken store, and reconnect never replays, so a transient SQLite failure silently lost the post. The append now retries with short backoff for transient blips; a persistent failure propagates and the websocket terminates loudly so the outage is operator-visible instead of silently dropping every subsequent post. Regression test covers both the absorbed-transient and escalation paths. * style(mattermost): format rebased ingress handler * docs(mattermost): document bounded auth-failure retries under deferred claims * fix(mattermost): guard the drain pump against stop racing the async prune stop() disposing before the startup pump finished pruning let the pump lazily create a fresh undisposed drain and dispatch after shutdown. The pump now re-checks running after the prune, and stop() disposes again after awaiting the pump so a drain created mid-race is torn down. Regression test blocks the prune across stop and asserts no dispatch. * fix(mattermost): serialize durable admissions to preserve lane order Concurrent websocket callbacks let a post in append-retry backoff be overtaken by its successor, inverting same-channel arrival order in the queue. Admissions now chain (order over latency, mirroring the iMessage admission tail); regression proves a retried post still lands ahead of a concurrently received one. * test(mattermost): assert lane order via dispatch sequence * fix(mattermost): stop() awaits in-flight admissions before disposal * fix(mattermost): satisfy ingress lint checks * fix(mattermost): honor envelope-level channel ids in the durable inspector Posts can carry their channel id on the post, the event data, or the broadcast envelope — the monitor dispatch honors all three, but the ingress inspector and claim-side validator required the nested field, rejecting valid posts as permanent and (via the storage-failure escalation) tearing down the socket for a failure that never happened, losing posts reconnect cannot replay. Both sites accept the three shapes; regression proves an envelope-level post dispatches.