Skip to content

Editing and Concurrency — Overview

The Arda items workspace is designed for several users working in parallel against the same tenant. Two of them can open the same item at the same time, edit cards from different browsers, or trigger bulk actions on overlapping selections. The data layer described in Data Flow and Caching caches server data in each browser tab — which is good for responsiveness, but means a tab’s view can fall out of step with the canonical state on the backend the moment another user (or another tab of the same user) writes.

This section documents the two mechanisms that close the loop:

  • A staleness signal that tells a user when the data on screen no longer matches what the backend would return for the same request, so they can refresh before acting.
  • A conflict-resolution preflight that catches the case where the user has already clicked a destructive bulk action against a selection that went stale between selection and click, and forces them to acknowledge before the action proceeds.

Both mechanisms work against the same ItemCardsProvider cache and the same rId-set diff primitive. They differ in when they fire and in what the user is asked to do.

Three concurrency scenarios shape the design:

ScenarioWhat happens without a signalWhere the user sees it first
User A and User B both have the same item open; A edits one of its cards.B keeps seeing the pre-edit cards. If B then clicks an action that the server has already invalidated (e.g., “add to order queue” on a card A just received), the action 409s.Detail panel open in B’s browser.
User A opens two tabs on the same items page; A edits in tab 1.Tab 2 keeps the pre-edit state in its cache and grid. If A switches to tab 2 and acts, same 409 risk as above; if A only reads, A sees inconsistent state across the tabs of one browser.Either tab.
User A starts a bulk operation on a 50-item selection, walks away, comes back, clicks Delete.The selection is captured at click time. Cards may have been added, removed, or re-issued in the intervening minutes. The destructive action proceeds against possibly-wrong assumptions.Delete modal in A’s browser.

The mechanisms below address each. The staleness signal covers the first two; the conflict-resolution preflight covers the third.

PageMechanism
Staleness SignalA local invalidation bus over BroadcastChannel for same-browser cross-tab propagation, plus a bounded interval poll for cross-browser propagation, both feeding the ItemCardsProvider cache. Surfaces in the UI as a stale-data banner with explicit Refresh / Dismiss controls.
Conflict ResolutionA snapshot-and-diff preflight (useBulkSelectionStaleGuard) that runs before a destructive bulk action proceeds. Compares each selected item’s cached rId set to a fresh server read; on mismatch, raises a banner and aborts so the user can refresh and re-click.

The system-level decisions that shape this section are recorded as ADRs:

The user-visible promise behind both mechanisms is documented as a product feature in Concurrent-Edit Awareness. The use-case catalogue in General Behaviours — Interactions and Items — Bulk Operations carries the user-flow scenarios that this section’s mechanisms must satisfy.