You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Some async operations do not accept an abort signal. This means calling code can fail to abort a long-running operation if the abort signal fires it's "abort" event while execution is suspended.
For example in the following code the signal can fire while the directory is being created and this code would be none the wiser:
```js
import fs from 'node:fs/promises'
async function doSomthing (signal) {
await fs.mkdir()
}
```
Instead we need to check if the signal is aborted before starting the async operation (to prevent doing needless work), and after, in case it aborted while the onward call was happening.
```js
import fs from 'node:fs/promises'
async function doSomthing (signal) {
signal.throwIfAborted()
await fs.mkdir()
signal.throwIfAborted()
}
```
This still waits for the operation to complete before checking the signal to see if it has been aborted. Instead we can use `raceSignal` to throw immediately, though the operation will continue in the background.
```js
import fs from 'node:fs/promises'
import { raceSignal } from 'race-signal'
async function doSomthing (signal) {
signal.throwIfAborted()
await raceSignal(fs.mkdir(), signal)
}
```
Synchronous operations have a similar problem when they are able to return optional promises, since the result may be awaited on. In this case we still need to check if the signal was aborted, though we only need to do it once.
```ts
interface MyOp<T> {
(signal: AbortSignal): Promise<T> | T
}
const fn: MyOp = (signal) => {
signal.throwIfAborted()
return 'hello'
}
// awaiting this shifts the continuation into the microtask queue
await fn(AbortSignal.timeout(1_000))
// could use optional await but `fn` cannot tell if it's being awaited on or not
// so it always has to check the signal
const p = fn(AbortSignal.timeout(1_000))
if (p.then) {
await p
}
```
This PR applies the above patterns to `@libp2p/crypto` keys, `@libp2p/peer-store` operations and `@libp2p/kad-dht` to ensure the `.provide` and `.findProviders` operations can be successfully aborted.
0 commit comments