diff --git a/docs/interfaces/server.serveroptions.md b/docs/interfaces/server.serveroptions.md index 8224f951..a82251f5 100644 --- a/docs/interfaces/server.serveroptions.md +++ b/docs/interfaces/server.serveroptions.md @@ -135,14 +135,21 @@ ___ • `Optional` **onDisconnect**: *undefined* \| (`ctx`: [*Context*](server.context.md), `code`: *number*, `reason`: *string*) => *void* \| *Promise*<*void*\> -Called when the socket/client closes/disconnects for -whatever reason. Provides the close event too. Beware -that this callback happens AFTER all subscriptions have -been gracefuly completed. +Called when the client disconnects for whatever reason after +he successfully went through the connection initialisation phase. +Provides the close event too. Beware that this callback happens +AFTER all subscriptions have been gracefully completed and BEFORE +the `onClose` callback. If you are interested in tracking the subscriptions completions, consider using the `onComplete` callback. +This callback will be called EXCLUSIVELY if the client connection +is acknowledged. Meaning, `onConnect` will be called before the `onDisconnect`. + +For tracking socket closures at any point in time, regardless +of the connection state - consider using the `onClose` callback. + ___ ### onError diff --git a/src/server.ts b/src/server.ts index caaadf89..3ba896d5 100644 --- a/src/server.ts +++ b/src/server.ts @@ -164,13 +164,20 @@ export interface ServerOptions { | boolean | void; /** - * Called when the socket/client closes/disconnects for - * whatever reason. Provides the close event too. Beware - * that this callback happens AFTER all subscriptions have - * been gracefuly completed. + * Called when the client disconnects for whatever reason after + * he successfully went through the connection initialisation phase. + * Provides the close event too. Beware that this callback happens + * AFTER all subscriptions have been gracefully completed and BEFORE + * the `onClose` callback. * * If you are interested in tracking the subscriptions completions, * consider using the `onComplete` callback. + * + * This callback will be called EXCLUSIVELY if the client connection + * is acknowledged. Meaning, `onConnect` will be called before the `onDisconnect`. + * + * For tracking socket closures at any point in time, regardless + * of the connection state - consider using the `onClose` callback. */ onDisconnect?: ( ctx: Context, @@ -679,7 +686,7 @@ export function makeServer(options: ServerOptions): Server { for (const sub of Object.values(ctx.subscriptions)) { await sub?.return?.(); } - await onDisconnect?.(ctx, code, reason); + if (ctx.acknowledged) await onDisconnect?.(ctx, code, reason); }; }, }; diff --git a/src/tests/server.ts b/src/tests/server.ts index c0f0db2c..341fb1c8 100644 --- a/src/tests/server.ts +++ b/src/tests/server.ts @@ -1392,7 +1392,7 @@ describe('Subscribe', () => { }); describe('Disconnect', () => { - it('should report close code and reason to disconnect callback', async (done) => { + it('should report close code and reason to disconnect callback after connection acknowledgement', async (done) => { const { url, waitForConnect } = await startTServer({ onDisconnect: (_ctx, code, reason) => { expect(code).toBe(4321); @@ -1412,4 +1412,18 @@ describe('Disconnect', () => { client.ws.close(4321, 'Byebye'); }); + + it('should not trigger the disconnect callback if connection is not acknowledged', async () => { + const { url, waitForClientClose } = await startTServer({ + onDisconnect: () => { + fail("Disconnect callback shouldn't be triggered"); + }, + }); + + const client = await createTClient(url); + + client.ws.close(4321, 'Byebye'); + + await waitForClientClose(); + }); });