Open Andrepuel opened 3 years ago
Looks like the listen()
promise is stuck in the Server async iterator.
Even after an connection is upgraded to WebSocket, it will still be handled by the iterator, waiting for a deferred promise called done
.
By doing the following workaround, I've managed to end the listening promise:
import { Application, Context } from 'https://deno.land/x/oak@v6.4.1/mod.ts';
const app = new Application();
app.use(async (ctx) => {
console.log('upgrading');
const socket = await ctx.upgrade();
// <--------------------------------- Workaround, force untracking this connection
ctx.request.serverRequest.done.resolve(new Error('force untrack'));
console.log('upgraded');
});
const controller = new AbortController();
const listening = app.listen({ port: 8000, signal: controller.signal });
await new Promise((ok) => setTimeout(ok, 100));
const ws = new WebSocket("ws://127.0.0.1:8000");
await new Promise<void>((ok, err) => {
ws.onopen = () => ok();
ws.onerror = (e) => {
console.error(e);
ok();
}
});
await new Promise((ok) => setTimeout(ok, 500));
ws.close();
await new Promise((ok) => setTimeout(ok, 500));
controller.abort();
console.log('aborting');
await Promise.all([
listening,
new Promise((_, err) => setTimeout(() => err(new Error("stuck")), 1000))
]);
However, the main process is still stuck. There is an async op that is leaking. By debugging the async op's I've figured out that a op named "ws next event" never returns. Even after the websocket is closed.
The second problem (stuck after listening finishes) is happening on the client side, not related to OAK.
Code to reproduce the issue: