PureScript Aff & JavaScript AbortController: Propagating Cancellation
0 reputation · 25 Oct 2024, 01:59 UTC
0 reputation · 25 Oct 2024, 01:59 UTC
The goal is to wire PureScript’s Aff cancellation model with the browser’s AbortController so that an Aff that performs an asynchronous fetch can be aborted cleanly by a JavaScript signal, and vice‑versa. This requires that cancellation of a parent Aff propagates to all nested child Aff computations, that timers used for timeouts are cleaned up promptly, and that the AbortController’s abort event is emitted when a PureScript cancel function is invoked.
Key constraints include the cooperative nature of Aff cancellation—an Aff must yield at cancellation points, otherwise the abort will not take effect immediately—and the lack of a built‑in abort signal interface in PureScript. Manual timers used for timeouts can leak if not cleared when the Aff is cancelled early. Bridging to AbortController also demands careful synchronization to avoid race conditions between the PureScript and JavaScript sides.
Unresolved decisions revolve around how to compose multiple cancelable Aff computations so that a parent’s cancellation cleanly terminates all children without resource leaks, and how to expose a type‑safe API that forwards a PureScript cancel function to an AbortController instance.
Aff computations so that a parent’s cancellation automatically propagates to all children, ensuring no dangling resources?Aff is cancelled?Aff cancel function to a JavaScript AbortController, guaranteeing that the controller’s abort event fires exactly when the PureScript cancel is invoked?33275 reputation · 25 Oct 2024, 04:45 UTC
To propagate PureScript Aff cancellation to a JavaScript AbortController, you must bind the lifecycle of the controller to the execution scope of the Aff. Because Aff cancellation is cooperative, the bridge must be established using a finalizer that triggers the abort() method when the PureScript runtime cancels the fiber.
The most reliable way to ensure the abort event fires is to use bracket or finally. This ensures that regardless of whether the Aff completes successfully, fails, or is cancelled, the underlying JavaScript resources are released.
-- Conceptual bridge pattern
withAbortController :: Aff a -> Aff a
withAbortController action =
bracket
(liftIO createAbortController) -- Acquire
(\controller -> liftIO (abort controller)) -- Release/Cancel
(\controller -> do
signal <- liftIO (getSignal controller)
actionWithSignal signal) -- Use
Aff runtime natively propagates cancellation from parent to child provided the child is awaited (e.g., via join or race). If a parent Aff is cancelled, all currently pending child Aff computations are also cancelled, which in turn triggers their respective bracket finalizers.setTimeout calls. Instead, use race between your primary task and a delay Aff. When the primary task wins, the delay Aff is cancelled; when the timeout wins, the primary task is cancelled. This ensures the runtime cleans up the underlying timer.AbortController should be instantiated immediately before the Aff starts and passed as a signal to the FFI call. This ensures the signal is active for the entire duration of the asynchronous operation.To verify the integration is working as expected:
fetch call in the withAbortController pattern. Cancel the Aff from the PureScript side and verify that the browser's Network tab marks the request as (canceled).console.log inside the bracket release function to confirm it executes immediately upon Aff cancellation.race between a long-running fetch and a short delay. Verify that the fetch is aborted when the timeout triggers.This approach assumes the use of a modern browser environment supporting AbortController and a standard Aff implementation (such as purescript-aff). It is assumed that the FFI wrappers for AbortController are correctly typed to handle the JavaScript Signal object. We assume the Aff is not performing long-running synchronous blocking operations, as these would prevent the runtime from reaching the cancellation point.
Diagnostic Detail Needed: Are you using a specific Aff library version or a custom effect wrapper that modifies the standard fiber cancellation behavior?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.