Skip to content

Board store needs operation-owned loading state instead of one shared Boolean #3305

Description

@Chris0Jeky

Summary

Every board sub-store currently writes the same state.loading Boolean directly. Independent asynchronous operations can overlap, so whichever operation settles first clears loading for all of them—even when another request still owns a visible board/list load.

Confirmed navigation race

  1. A mutation for board A begins and sets state.loading = true.
  2. The user navigates to board B; its detail read begins and also sets the same Boolean to true.
  3. The board-A mutation resolves first. Its finally writes state.loading = false.
  4. Board B is still on the wire, but BoardView/PaperBoardView lose skeleton or retry-disabled state early and may expose stale/empty detail until the read settles.

The same ownership failure exists between overlapping board-list/detail reads and card, column, label, or comment mutations. Post-await board-state guards do not fix the flag because each finally still clears it unconditionally.

Expected design

Replace direct shared-Boolean ownership with one store-level operation mechanism, such as epoch-aware loading tokens or a reset-safe active-operation set:

  • starting an operation returns its own token;
  • settling removes only that token;
  • loading remains true while any current-epoch token exists;
  • logout/reset invalidates old tokens and clears the visible state synchronously;
  • stale/cancelled generations cannot strand loading true or clear a newer session's owner;
  • board-list/detail generation rules and existing mutation return/error behavior remain intact.

Do not solve this with scattered board-id conditions: list reads, detail reads, and mutations overlap across different contexts.

Acceptance

  • Deferred-promise regressions for old-board mutation vs new-board detail load, overlapping mutations, and logout/reset with an old request still settling.
  • Existing list-share, detail-generation, queued-background-refresh, and cancellation tests remain green.
  • All direct state.loading.value = true/false writes in board action modules either move behind the shared owner or are explicitly justified as reset/demo boundaries.
  • Frontend lint, typecheck, build, full tests, and exact-head hosted CI pass.

Audit provenance

Found during the sibling async-integrity pass that produced #3299, #3301, and #3303. Kept separate because it is a cross-module ownership invariant rather than a local fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority IIThe active direction's next tranche: wedge capabilities, significant defects, near-term hardening.bugSomething isn't workingfrontendPrimary implementation impact in Vue/TypeScript UI and client runtime.tech-debtDebt cleanup or deferred engineering quality work with limited product-surface change.testingTest coverage, harnesses, regression prevention, and verification pipeline work.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions