[whatwg/dom] Variable strength aborting (Issue #1215)

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