Interruptible Request Diagnostics Design
Goal
Use FoldKit 0.129’s interruptible Commands in the request diagnostics demo so a reload replaces an in-flight metrics request without allowing stale results to update the application.
Scope
This slice changes only apps/web/src/apps/request-diagnostics/. It demonstrates app-owned cancellation with the existing foldkit/http API client and does not add an Astro integration API, remote chart-data API, or new query controls.
Command Boundary
FetchMetrics becomes Command.Interruptible.define. Its key is a fixed diagnostics-dataset identity because every invocation loads the same /api/request-diagnostics resource. The command remains responsible only for HTTP work and maps its success and failure results to the existing LoadedMetrics and FailedLoad Messages.
The application owns interruption. FetchMetrics.Interrupt is dispatched from the update layer, not from the Astro integration or chart primitives.
Message Flow
- Initialisation dispatches
FetchMetrics()and the runtime registers that invocation under the diagnostics key. - A
ClickedReloadMessage inLoading,Ready,Filtered, orFailedtransitions the explorer toCancellingand returns onlyFetchMetrics.Interrupt. - The interrupt command dispatches
CompletedCancelFetchMetrics, a new past-tense fact carrying its outcome. - The state-machine handler for that fact transitions to
Loadingand dispatchesFetchMetrics()as the replacement request. - A successfully interrupted request cannot dispatch
LoadedMetricsorFailedLoad; the replacement result completes the usual state-machine transition.
The update must never return the interrupt command and its replacement in the same batch because command execution order inside a batch is not guaranteed.
State and UI
Cancelling represents the interrupt window, and Loading represents the replacement request. A second reload is ignored while Cancelling, preventing repeated clicks from creating duplicate replacement requests. The existing reload control stays enabled so a user can replace an in-flight request.
Error Handling
The existing HTTP failure mapping remains unchanged. The interrupt outcome is observational: both Interrupted and NotFound start the requested replacement load. NotFound means the old request had already completed or was no longer registered; it is not an application error.
Tests
- Command test:
FetchMetricsstill decodes the Astro API response when provided a fetch client. - Update tests: reload during loading returns only the interrupt command, and the interrupt outcome returns the replacement fetch command.
- Existing state-machine tests continue to prove the successful and failed request transitions.
Non-Goals
- Query or typeahead controls.
- Cancelling work on Astro route exit.
- Any change to
@opsydyn/astro-foldkitor@opsydyn/foldkit-vizpublic APIs.