Context
Upload lifecycle state changes frequently (progress updates, pauses, retries, failures) and may occur while:
- routes change
- components unmount/remount
- tabs reload
- multiple uploads run concurrently
UI logic that incrementally mutates state based on events is prone to:
- missed events
- state drift
- inconsistent recovery after reloads
- tight coupling to internal event taxonomies
Given uploads are infrastructure-level concerns, correctness and recoverability are more important than micro-optimizations.
Decision
The UploadEngine is the single source of truth for all upload state.
UI layers:
- do not derive state from events
- treat upload events as invalidation signals only
- always rehydrate state via full snapshots:
UploadEngine.list();
No UI component maintains partial or derived upload lifecycle state.
Consequences
- UI state is always replaceable and recoverable
- Reloads and missed events do not corrupt upload visibility
- UI is decoupled from engine event taxonomy
- New engine events do not require UI changes
- Correctness is prioritized over incremental updates
Notes
- This decision intentionally favors snapshot-based synchronization over event-driven mutation.
- Events exist to signal that something changed, not to describe what changed.
- This ADR enables a resilient global upload UI that behaves predictably under failure, reloads, and future engine evolution.