Rather than rely on second hand information from someone else (which might not be correct), why not just do a test and find out for yourself (or review the source code)?
Here's a reproducible example which indicates that — when using Deno@1.28.2 with Oak@11.1.0 — the server gracefully shuts down: it still responds to a pending request even after the AbortSignal
is aborted:
so-74600368.ts
:
import {
Application,
type Context,
} from "https://deno.land/x/oak@v11.1.0/mod.ts";
import { delay } from "https://deno.land/std@0.166.0/async/delay.ts";
async function sendRequestAndLogResponseText(): Promise<void> {
try {
const response = await fetch("http://localhost:8000/");
if (!response.ok) {
throw new Error(`Response not OK (Status code: ${response.status})`);
}
const text = await response.text();
console.log(performance.now(), text);
} catch (ex) {
console.error(ex);
}
}
async function sendSquentialRequsets(numOfRequests: number): Promise<void> {
for (let i = 0; i < numOfRequests; i += 1) {
await sendRequestAndLogResponseText();
}
}
function printStartupMessage({ hostname, port, secure }: {
hostname: string;
port: number;
secure?: boolean;
}): void {
if (!hostname || hostname === "0.0.0.0") hostname = "localhost";
const address =
new URL(`http${secure ? "s" : ""}://${hostname}:${port}/`).href;
console.log(`Listening at ${address}`);
console.log("Use ctrl+c to stop");
}
async function main() {
const log = new Map<Context, boolean>();
const controller = new AbortController();
controller.signal.addEventListener("abort", () => {
console.log(performance.now(), "Abort method invoked");
});
const app = new Application();
app.use(async (ctx) => {
log.set(ctx, false);
if (log.size > 2) {
console.log(performance.now(), "Aborting");
controller.abort(new Error("Received third request. Aborting now."));
}
// A bit of artificial delay, to ensure that no unaccounted for latency
// might cause a non-deterministic/unexpected result:
await delay(300);
ctx.response.body = `Response OK: (#${log.size})`;
log.set(ctx, true);
});
app.addEventListener("listen", (ev) => {
console.log(performance.now(), "Server starting");
printStartupMessage(ev);
});
const listenerPromise = app.listen({
hostname: "localhost",
port: 8000,
signal: controller.signal,
})
.then(() => {
console.log(performance.now(), "Server stopped");
return { type: "server", ok: true };
})
.catch((reason) => ({ type: "server", ok: false, reason }));
const requestsPromise = sendSquentialRequsets(3)
.then(() => {
console.log(performance.now(), "All responses OK");
return { type: "requests", ok: true };
})
.catch((reason) => ({ type: "requests", ok: false, reason }));
const results = await Promise.allSettled([listenerPromise, requestsPromise]);
for (const result of results) console.log(result);
const allResponsesSent = [...log.values()].every(Boolean);
console.log({ allResponsesSent });
}
if (import.meta.main) main();
% deno --version
deno 1.28.2 (release, x86_64-apple-darwin)
v8 10.9.194.1
typescript 4.8.3
% deno run --allow-net=localhost so-74600368.ts
62 Server starting
Listening at http://127.0.0.1:8000/
Use ctrl+c to stop
378 Response OK: (#1)
682 Response OK: (#2)
682 Aborting
682 Abort method invoked
990 Server stopped
992 Response OK: (#3)
992 All responses OK
{ status: "fulfilled", value: { type: "server", ok: true } }
{ status: "fulfilled", value: { type: "requests", ok: true } }
{ allResponsesSent: true }