- From: bojavou <notifications@github.com>
- Date: Tue, 04 Jul 2023 17:14:48 -0700
- To: whatwg/dom <dom@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/dom/issues/1215@github.com>
Some systems distinguish between a graceful shutdown and a forceful termination. This distinction cannot be delivered through `AbortController`. It would be nice if the same channel could be used to deliver both.
The current interface might extend to this cleanly, without breaking anything. The delivered `Event` could provide a boolean `.force` indicating whether a forceful abort was requested or not. `AbortController.prototype.abort()` could take the option `{ force: true }` to request a forceful abort. A second call to `abort()` could be allowed, for requesting forceful abort after a standard abort was already requested.
2 levels of strength seem sufficient. I've never seen a use for further distinctions.
Some usage patterns.
* Request forceful abort immediately. Everything is terminated as quickly as possible.
This might be tied to a more forceful user control, eg Kill vs Cancel.
```js
const reason = new Error('User clicked Kill Now')
controller.abort(reason, { force: true })
```
```js
const reason = new Error('User clicked Cancel')
controller.abort(reason)
```
```js
function aborted (event) {
if (event.force) {
kill()
} else {
cancel()
}
}
```
* Request standard abort with a time limit. Request forceful abort if it times out.
This might be useful where closing a connection can take a long time. The close logic can have retries to tolerate transient network errors, with delays between them. If the process drags on too long, terminate.
```js
process.on('SIGINT', () => {
// Await close of everything watching the signal
Promise.allSettled(clients.map(client => client.done))
.then(() => { process.exit() })
// Request standard shutdown
controller.abort()
// Time out standard shutdown in 5 seconds
// Unref the timer to prevent it keeping the process alive
const timer = setTimeout(() => {
const reason = new Error('Closing connection timed out')
controller.abort(reason, { force: true })
}, 5000)
timer.unref()
})
```
* Offer users 2 levels of interrupt.
This is a common pattern in the CLI interface of servers. The first CTRL+C initiates a graceful shutdown: the server stops accepting new connections and waits for existing connections to complete normally. A second CTRL+C during graceful shutdown terminates all open connections without waiting for completion and shuts down immediately.
```sh
$ ./server
Serving 112 requests
Interrupt received, shutting down
Completed 52/112 requests
Second interrupt received, terminating open connections
```
```js
let shuttingDown = false
process.on('SIGINT', () => {
if (!shuttingDown) {
// First interrupt, start graceful shutdown
shuttingDown = true
program.closed.then(() => { process.exit() })
controller.abort()
} else {
// Second interrupt, kill everything now
controller.abort(undefined, { force: true })
}
})
```
--
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/dom/issues/1215
You are receiving this because you are subscribed to this thread.
Message ID: <whatwg/dom/issues/1215@github.com>
Received on Wednesday, 5 July 2023 00:14:54 UTC