Closed ondrej-stanek-ozobot closed 11 months ago
This PR is a draft, if the concept of raceAndCancel
is welcomed by the maintainers, we are happy to bring it to production quality, add tests, etc..
This is an example how a timeout for a (cancellable) promise can be implemented using raceAndCancel
:
/**
* Guards the duration of a cancellable promise resolution with a timeout.
* If promise resolves before the timeout, its result is returned.
* Otherwise, the promise is cancelled and timeout exception is thrown.
*
* @param promise promise to be guarded with timeout, has to implement the CancellablePromise contract
* @param timeout_ms
* @returns value of the resolved promise
*/
export function timeoutGuard<T extends CancellablePromise<unknown>>(
promise: T,
timeout_ms: number
) {
// promise that never resolves, but throws a timeout error after `timeout_ms` lapsed
const timeout = CancellablePromise.delay(timeout_ms).then(
() => { throw new Error("Timeout") }
)
return raceAndCancel([ promise, timeout ])
}
Hey @ondrej-stanek-ozobot, nice work. My only concern is, I am not sure how frequently this new function would be used, and I would prefer to keep the API surface area of this library relatively small.
Is there a reason why raceAndCancel
needs to be part of the real-cancellable-promise source code? It seems like this function is straightforward to implement in userland.
Some ideas for how we could proceed:
Thanks 😀
I totally understand, no problem.
We are using this (and other) helper functions quite extensively in our codebase, and the real-cancellable-promise
became a cornerstone on which we build the structured concurrency patterns. Thanks for this great project!
We are thinking about publishing the helpers for structured concurrency. If the intention is to keep real-cancellable-promise
relatively small, perhaps we could publish the helpers as a separate package that tightly depends on real-cancellable-promise
?
Because the real-cancellable-promise
is such a great fit, I wanted to ask if you have interest in structured concurrency and related software patterns?
Publishing your structured concurrency helper functions as a new npm package is a cool idea! Let me know if you end up doing that.
Motivation:
The core concept of Structured concurrency [1] requires that "all spawned threads have completed before exit". The classic implementation of
Promise.race
doesn't meet this requirement, as the returned promise finishes sooner than any of the other promises and the other promises are kept running until completion. Therefore, thePromise.race
violates the basic principle of structured concurrency when used as a building block for combining parallel tasks.We propose a simple wrapper for the
Promise.race
that ensures all remaining promises are automatically cancelled upon completion of the first one. We name the wrapperraceAndCancel
, however, we are open to any other naming suggestions.Example of use:
[1] https://en.wikipedia.org/wiki/Structured_concurrency