Skip to content

inbox: openNodeDetail/openDetailPane has no stale-response guard #97

Description

@BorisTyshkevich

Spotted during /code-review on #85's branch (table-detail loading spinner work), but the underlying race predates that PR — it exists in the single-await version of openNodeDetail too, not something #85 introduced.

Where: src/ui/app.js openNodeDetail(node, targetDoc) calls openDetailPane(app, node, detail, targetDoc) (src/ui/schema-detail.js:23), which unconditionally removes whatever .schema-detail pane is currently mounted and replaces it, with no check that node is still the most-recently-requested node.

Failure scenario: user clicks table A in the fullscreen schema graph (starts ch.loadTableDetail for A), then quickly clicks table B before A's fetch resolves (starts a separate fetch for B, mounts B's pane/ring). If A's fetch resolves after B's, A's openDetailPane call fires last and silently replaces B's pane + selection ring with A's stale data — last-resolved-wins instead of last-clicked-wins. No crash, but the displayed detail can mismatch what's highlighted as selected.

Why deferred: out of scope for #85 (UI polish issue); fixing requires a request-identity guard (e.g. stash a request token/node id and check it before the final openDetailPane call), which is a small but separate behavioral change deserving its own test coverage.

Suggested fix shape: track a per-overlay "latest requested node id" (or a monotonic request counter) in openNodeDetail; before the final openDetailPane call, check the request is still current and no-op otherwise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    inboxFiled mid-task; not yet triaged into the roadmap

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions