Skip to content

fix(realtime): catch up missed board events after rejoin - #3320

Merged
Chris0Jeky merged 11 commits into
mainfrom
codex/3319-realtime-recovery
Sep 21, 2026
Merged

Chris0Jeky merged 11 commits into
mainfrom
codex/3319-realtime-recovery

Conversation

@Chris0Jeky

@Chris0Jeky Chris0Jeky commented Sep 21, 2026

Copy link
Copy Markdown
Owner

Closes #3319.

Repair

  • Rejoin acknowledgement, not transport reconnection alone, retires polling fallback.
  • Successful current-generation joins discharge pending recovery with one authoritative catch-up.
  • Fallback ticks, mutation refreshes and recovery reads share one bounded active/pending slot, so an older fallback read cannot consume catch-up through store-level request deduplication.
  • Navigation during a delayed rejoin transfers recovery and polling to the latest requested board. Stop discards the obligation. Failed latest-board joins keep polling the right board.
  • Rejoin callback failures are contained; optional editing-presence failure cannot suppress catch-up.
  • A second disconnect before acknowledgement cannot disable its new fallback interval. Stale connection callbacks cannot start polling for a replacement connection.

No dependency, workflow, backend or store changes. The separate server-side JoinBoard investigation #1521 remains open.

Exact current head

072d252b0e258fd4a28443f547c6ea3e34ee49bb, based on main 307c3b8b50bec1cb0bfaea3e570a942bcb1d4451.

Four files: the controller, ten new recovery cases, and two existing reconnect assertions updated to require exactly one catch-up while independently proving periodic polling stops. No assertions are skipped or weakened to allow missing recovery.

Evidence and review history

  1. Supplementary real-TypeScript-controller / synthetic-SignalR probe: short disconnect and failed rejoin both failed against main and passed after the initial repair. This is unit-level control-flow evidence, not a real server/browser or full Vitest run.
  2. First implementation 6fb7f2d...: normal Ubuntu frontend lint/typecheck/build/PWA validation passed; all eight then-new recovery cases passed. Full JUnit recorded 7,158 tests, one failure, zero errors. The sole failure was an older resilience test asserting no reconnect read. Run: https://github.com/Chris0Jeky/Taskdeck/actions/runs/35591987360 . That outdated expectation was corrected in 3cc235f... without changing production behavior.
  3. Independent Codex review on 3cc235f... found two valid P2 gaps: an in-flight fallback could swallow catch-up, and navigation during rejoin could discard recovery. Both were reproduced before correction and are addressed by current head. The supplementary probe now passes 4/4; ten formal recovery tests include both schedules and failed recovery transfer. Inline threads contain detailed replies.
  4. Current-head full GitHub Actions and repeat Codex review have been requested. Earlier head results are not claimed as final-head validation.

Local npm registry DNS failed (EAI_AGAIN), and installed Node 22 is below the repository's Node 24 contract. Locked-dependency runtime qualification therefore uses normal hosted Actions, without engine/dependency/workflow bypasses.

Handoff

Keep draft until current-head frontend/full CI and the repeat review are inspected. Recheck current main and changed paths before continuing. Do not merge, alter release gates or infer that successful unit checks qualify real-server SignalR behavior. This PR does not own board/session-store invalidation (#3305/#3306/#3324).

Copy link
Copy Markdown
Owner Author

@codex review

Please review exact head 3cc235f6fbb98e18d8a67f34f6411616fe65b97a against main 307c3b8b50bec1cb0bfaea3e570a942bcb1d4451, especially subscription-generation ownership, fallback lifetime, reconnect/disconnect overlap, coalesced catch-up and failure containment.

The first implementation head 6fb7f2d2a14b303f98ddea4267752837ba508841 passed lint/typecheck/build/PWA validation and all eight new recovery cases. Full Ubuntu JUnit: 7,158 tests, one failure, zero errors. The sole failure was the older degradedMode.spec.ts assertion that reconnect performs zero reads. This head replaces it with an explicit exactly-one catch-up assertion and retains the independent no-further-periodic-poll assertion; no production code was changed to accommodate a test.

Run: https://github.com/Chris0Jeky/Taskdeck/actions/runs/35591987360 ; JUnit artifact 10634884046. Current-head CI is pending. Keep draft; the server-side JoinBoard investigation #1521 remains separate.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 21, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-21T21:07:33.445274Z 51448e9 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3cc235f6fb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts

Copy link
Copy Markdown
Owner Author

@codex review

Please re-review head 072d252b0e258fd4a28443f547c6ea3e34ee49bb, especially the fixes for both P2 findings on 3cc235f. Fallback, mutation and catch-up reads now share a bounded active/pending slot, and recovery/polling transfer to the latest board during a queued rejoin. Both inline threads have implementation and regression details. This branch now adds ten recovery cases. Supplementary real-controller transport probes: original controls 2/2 retained, review schedules red 2/2 before repair and green 2/2 after repair. Hosted exact-head CI remains the runtime gate; keep draft.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 072d252b0e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
@Chris0Jeky
Chris0Jeky marked this pull request as ready for review September 21, 2026 18:21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb35340ca5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/taskdeck-web/src/tests/composables/useBoardRealtime.spec.ts Outdated
Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts
Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
@Chris0Jeky
Chris0Jeky force-pushed the codex/3319-realtime-recovery branch from fa44ae0 to 9fcae6f Compare September 21, 2026 19:02
@Chris0Jeky
Chris0Jeky force-pushed the codex/3319-realtime-recovery branch from 9fcae6f to eda04b0 Compare September 21, 2026 20:15
@Chris0Jeky

Copy link
Copy Markdown
Owner Author

@codex review\n\nPlease review exact current head �da04b07afb8f00e46106e911bb3071615fd1088 against base b830ed1960648662f92090e2970491d163f93a7. Focus on rejoin acknowledgement, recovery/polling ownership transfer, fallback/catch-up deduplication, stale connection callbacks, and failed latest-board rejoin behavior. Earlier review findings were repaired; this is the one current-head review request for the rebased PR.

@Chris0Jeky

Copy link
Copy Markdown
Owner Author

Correction to the prior review request: exact current head is eda04b0 and base is fb830ed. The prior comment was malformed by PowerShell quoting; the @codex review trigger was already submitted.

@chatgpt-codex-connector

Copy link
Copy Markdown

Review findings

P2 — Version recovery completion across consecutive reconnects

A catch-up from an earlier reconnect can still discharge a newer recovery obligation. Every reconnect sets the shared recoveryPending flag, but a successful recovery read unconditionally clears that flag and stops fallback polling without verifying which reconnect initiated the read. frontend/taskdeck-web/src/composables/useBoardRealtime.tsL118-L133 frontend/taskdeck-web/src/composables/useBoardRealtime.tsL208-L226

Reproduction sequence:

  1. First reconnect acknowledges and starts its catch-up.
  2. A second disconnect occurs while that read is in flight, setting recoveryPending again.
  3. The first read resolves while the second JoinBoard is still awaiting acknowledgement.
  4. The old completion clears recoveryPending and stops the new fallback timer.
  5. The second join then sees no pending recovery and schedules no post-acknowledgement catch-up. frontend/taskdeck-web/src/composables/useBoardRealtime.tsL305-L312

A mutation missed during the second outage can therefore remain absent. Recovery completion needs an epoch/generation token so only the recovery generation that owns a read can discharge its obligation.

P2 — A skipped view refresh is still treated as successful recovery

BoardView returns undefined when the requested refresh no longer matches its local board ID. frontend/taskdeck-web/src/views/BoardView.vueL131-L138 The controller treats every result except literal false as success, clearing recovery and stopping fallback polling. frontend/taskdeck-web/src/composables/useBoardRealtime.tsL118-L133

This remains reachable because route navigation updates boardId before loading the new board, but does not call realtime.switchBoard until that load completes. frontend/taskdeck-web/src/views/BoardView.vueL339-L360 If the old board rejoins during that interval, its catch-up is skipped by the adapter yet counted as successful. The subsequent switch therefore does not inherit recovery, so a mutation to the new board between its HTTP snapshot and SignalR join may be missed.

The adapter should return false for skipped reads, or the controller’s requested board should be switched before awaiting the route load.

Review status

Reviewed exact head eda04b07afb8f00e46106e911bb3071615fd1088 against exact base fb830ed1960648662f92090e2970491d163f93a7. No repository files were changed, so there was no commit and—per instruction—no follow-up PR was created.

I could not publish the review directly to GitHub because this environment has neither an authenticated gh session nor GH_TOKEN.

The repository’s human-action ledger currently contains 42 open items, including maintainer-only credential rotation, real-device validation, repository/CI governance decisions, and product rulings. OUTSTANDING_TASKS.mdL143-L144 OUTSTANDING_TASKS.mdL165-L168

Checks

  • git rev-parse HEAD — confirmed eda04b07afb8f00e46106e911bb3071615fd1088.
  • git rev-parse fb830ed1960648662f92090e2970491d163f93a7 — confirmed the supplied base exists locally.
  • npm run typecheck
  • npx vitest --run --maxWorkers=2 src/tests/composables/boardRealtimeRecovery.spec.ts src/tests/composables/useBoardRealtime.spec.ts src/tests/resilience/degradedMode.spec.ts src/tests/store/board/boardCrudStore.spec.ts — 4 files and 117 tests passed.
  • git status --short --branch — clean working tree.
  • ⚠️ gh pr view --json number,url,title,headRefOid,baseRefOid,isDraft,state,statusCheckRollup,reviewDecision — unavailable because GitHub CLI authentication is not configured.

View task →

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: eda04b07af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts
Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
@Chris0Jeky

Copy link
Copy Markdown
Owner Author

@codex review

Fresh review request for exact current head 90d41ea against base fb830ed. The prior current-head review findings are fixed in commits 1e9029c and 90d41ea: reconnect recovery completion is generation-scoped, queued successors retarget newer recovery generations, and BoardView reports skipped stale/unmounted refreshes as false. Please review only the fix diff and confirm whether any merge-blocking defect remains.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 90d41eaf1f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread frontend/taskdeck-web/src/composables/useBoardRealtime.ts Outdated
@Chris0Jeky

Copy link
Copy Markdown
Owner Author

@codex review

Fresh review request for exact current head 51448e9 against base fb830ed. The previous P2 threads are addressed by generation-scoped recovery, queued-old-generation protection, stale-view false signaling, and affirmative commit enforcement. Review only the final fix diff for merge-blocking defects.

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 51448e91bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Chris0Jeky
Chris0Jeky merged commit f001dd9 into main Sep 21, 2026
36 checks passed
@Chris0Jeky
Chris0Jeky deleted the codex/3319-realtime-recovery branch September 21, 2026 22:04
@github-project-automation github-project-automation Bot moved this from Pending to Done in Taskdeck Execution Sep 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Reconcile board state after realtime reconnect and retain polling until rejoin succeeds

1 participant