mirror of
https://github.com/denoland/deno.git
synced 2025-01-11 00:21:05 -05:00
feat(ext/http): ref/unref for server (#19197)
Add `ref` and `unref` to return value from `Deno.serve`. Unblocks #3326.
This commit is contained in:
parent
af72a9c657
commit
7f5290b694
3 changed files with 54 additions and 2 deletions
|
@ -10,6 +10,7 @@ import {
|
|||
assertThrows,
|
||||
Deferred,
|
||||
deferred,
|
||||
execCode,
|
||||
fail,
|
||||
} from "./test_util.ts";
|
||||
|
||||
|
@ -56,6 +57,21 @@ Deno.test(async function httpServerShutsDownPortBeforeResolving() {
|
|||
listener!.close();
|
||||
});
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { read: true, run: true } },
|
||||
async function httpServerUnref() {
|
||||
const [statusCode, _output] = await execCode(`
|
||||
async function main() {
|
||||
const server = Deno.serve({ port: 4501, handler: () => null });
|
||||
server.unref();
|
||||
await server.finished; // This doesn't block the program from exiting
|
||||
}
|
||||
main();
|
||||
`);
|
||||
assertEquals(statusCode, 0);
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(async function httpServerCanResolveHostnames() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
|
12
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
12
cli/tsc/dts/lib.deno.unstable.d.ts
vendored
|
@ -1312,7 +1312,19 @@ declare namespace Deno {
|
|||
* the signal passed to {@linkcode ServeOptions.signal}.
|
||||
*/
|
||||
finished: Promise<void>;
|
||||
|
||||
/**
|
||||
* Make the server block the event loop from finishing.
|
||||
*
|
||||
* Note: the server blocks the event loop from finishing by default.
|
||||
* This method is only meaningful after `.unref()` is called.
|
||||
*/
|
||||
ref(): void;
|
||||
|
||||
/** Make the server not block the event loop from finishing. */
|
||||
unref(): void;
|
||||
}
|
||||
|
||||
/** **UNSTABLE**: New API, yet to be vetted.
|
||||
*
|
||||
* Serves HTTP requests with the given handler.
|
||||
|
|
|
@ -43,6 +43,7 @@ const {
|
|||
SetPrototypeAdd,
|
||||
SetPrototypeDelete,
|
||||
Symbol,
|
||||
SymbolFor,
|
||||
TypeError,
|
||||
Uint8Array,
|
||||
Uint8ArrayPrototype,
|
||||
|
@ -660,13 +661,22 @@ function serve(arg1, arg2) {
|
|||
|
||||
onListen({ port: listenOpts.port });
|
||||
|
||||
let ref = true;
|
||||
let currentPromise = null;
|
||||
const promiseIdSymbol = SymbolFor("Deno.core.internalPromiseId");
|
||||
|
||||
// Run the server
|
||||
const finished = (async () => {
|
||||
while (true) {
|
||||
const rid = context.serverRid;
|
||||
let req;
|
||||
try {
|
||||
req = await op_http_wait(rid);
|
||||
currentPromise = op_http_wait(rid);
|
||||
if (!ref) {
|
||||
core.unrefOp(currentPromise[promiseIdSymbol]);
|
||||
}
|
||||
req = await currentPromise;
|
||||
currentPromise = null;
|
||||
} catch (error) {
|
||||
if (ObjectPrototypeIsPrototypeOf(BadResourcePrototype, error)) {
|
||||
break;
|
||||
|
@ -691,7 +701,21 @@ function serve(arg1, arg2) {
|
|||
}
|
||||
})();
|
||||
|
||||
return { finished };
|
||||
return {
|
||||
finished,
|
||||
ref() {
|
||||
ref = true;
|
||||
if (currentPromise) {
|
||||
core.refOp(currentPromise[promiseIdSymbol]);
|
||||
}
|
||||
},
|
||||
unref() {
|
||||
ref = false;
|
||||
if (currentPromise) {
|
||||
core.unrefOp(currentPromise[promiseIdSymbol]);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
internals.addTrailers = addTrailers;
|
||||
|
|
Loading…
Reference in a new issue