Skip to content

Harden StatusChannel Action Cable stream lifecycle ownership - #1405

Draft
ivankuznetsov wants to merge 5 commits into
mainfrom
place-the-race-fix-in-the-authoritative-ac-coding-4c1bbdcd
Draft

ivankuznetsov wants to merge 5 commits into
mainfrom
place-the-race-fix-in-the-authoritative-ac-coding-4c1bbdcd

Conversation

@ivankuznetsov

Copy link
Copy Markdown
Owner

Summary

Keeps Hive's application-owned StatusChannel lifecycle fence in place and extends it across start, targeted stop, and global stop. Adds deterministic race regressions, a reusable real-channel lifecycle contract, Solid Cable coverage, browser checks, stress controls, and rollback/provenance documentation.

Why

Rails 8.1.3.1 does not yet provide the required teardown fencing, so late registration, confirmation, duplicate cleanup, and lease leaks must remain guarded locally until a released upstream fix is proven.

Validation

  • Focused channel: 24 tests, 135 assertions
  • Solid Cable: 5 tests, 47 assertions
  • Stress: seed 42837, 100 iterations per race window (25 tests, 1,935 assertions)
  • Focused browser: 30 tests, 222 assertions
  • Full Web: 344 tests, 2,055 assertions; full system: 63 tests, 636 assertions
  • RuboCop clean; Gemfile, lockfile, and cable.yml unchanged

The unchanged golden-path fixture remains non-green because mandatory plan review launches a real Codex process beyond its 90-second bound; this isolation gap is documented in wiki/gaps.md.

@ivankuznetsov
ivankuznetsov force-pushed the place-the-race-fix-in-the-authoritative-ac-coding-4c1bbdcd branch from 4beea13 to 1abc3a3 Compare September 6, 2026 15:33
@ivankuznetsov
ivankuznetsov force-pushed the place-the-race-fix-in-the-authoritative-ac-coding-4c1bbdcd branch from 1abc3a3 to bffa9cf Compare September 6, 2026 16:14
Account for the six production configuration lines added for the Solid Cable test database.

Hive-Task-Slug: place-the-race-fix-in-the-authoritative-ac-coding-4c1bbdcd
Hive-Fix-Pass: 01
Hive-Fix-Phase: ci
@ivankuznetsov

Copy link
Copy Markdown
Owner Author

Reviewer: codex-ce-code-review - Pass 01

High

  • Clean up partial adapter registration on failure (web/app/channels/status_channel.rb:314-322): Solid Cable inserts the handler into SubscriberMap before Listener#add_channel queries last_message_id; if that query raises, this code clears the pending attempt and only unsubscribes streams, permanently losing cleanup ownership. An in-memory reproduction with the real Rails subscriber map left one adapter handler with empty channel registries and one reconnect. Cover this real failure boundary and remove the retained handler to satisfy R7.
  • Fence the final initial-subscription confirmation (web/app/channels/status_channel.rb:223-227): Registration can resolve its confirmation deferral before Rails finishes subscribe_to_channel; teardown followed by Rails' final ensure_confirmation_sent then emits confirm_subscription on the dead channel. This ordering reproduced with the real Rails channel base. Coordinate every confirmation path with teardown and add the inverse ordering regression required by R5; existing helpers resolve the initial deferral before registration.
  • Make delivery and teardown mutually ordered (web/app/channels/status_channel.rb:171-178): status_stream_deliverable? releases the monitor before invoking the callback or transmitting, so teardown can finish after the successful check but before delivery. A bounded in-memory barrier reproduced a payload after teardown with unsubscribed? == true and empty streams. Fence the delivery operation itself and cover this window to meet the no-late-payload contract.
  • Exercise active leases in the race and real-adapter contracts (web/test/support/status_channel_stream_lifecycle_contract.rb:228-246; web/test/channels/status_channel_test.rb:615-638): These helpers call bare stream_from, bypassing subscription activation and broadcaster lease acquisition; neither race window nor the shared Async/Solid contract counts lease release. Separate ChannelStub lease tests cannot prove the required interaction. Add active-lease setup and independent exactly-once release assertions for R4/R5/R9.
  • Add the required browser transport teardown proof (web/test/system/kanban_board_test.rb:884-929): The added assertions observe server notifications and catch-up calls, release registration before waiting for teardown, and expect confirmation before teardown; the unfenced implementation can satisfy that ordering. They neither capture received payload frames nor force registration completion after server teardown. Add bounded transport observations for that window to satisfy U3/R9.
  • Complete the mandatory golden-path acceptance gate (wiki/log.d/20260830T184156Z-action-cable-stream-lifecycle.md:34-39): The retained evidence explicitly records two unsuccessful golden-path attempts and no passing run. The documented baseline harness blocker is not a plan-deferred exception: R9 and the current Definition of Done require this gate. Resolve or isolate the harness blocker and retain passing evidence before marking acceptance complete.

Medium

Nit

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.

1 participant