From 947f8fd4fa77b2e04b6df705b94f13dccdb83fba Mon Sep 17 00:00:00 2001 From: Iain Sproat <68657+iainsproat@users.noreply.github.com> Date: Wed, 5 Feb 2025 15:16:22 +0000 Subject: [PATCH] fix(server/database streams): remove event listener on batch completion (#3938) --- packages/preview-service/src/server/routes/api.ts | 8 +++++++- packages/preview-service/src/server/routes/objects.ts | 8 +++++++- packages/server/modules/core/rest/diffDownload.ts | 8 +++++++- packages/server/modules/core/rest/download.ts | 9 ++++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/packages/preview-service/src/server/routes/api.ts b/packages/preview-service/src/server/routes/api.ts index 5da6d4192..2d33b479a 100644 --- a/packages/preview-service/src/server/routes/api.ts +++ b/packages/preview-service/src/server/routes/api.ts @@ -36,12 +36,18 @@ const apiRouterFactory = () => { streamId: req.params.streamId, objectIds: getObjectsRequestBody.objects }) + // https://knexjs.org/faq/recipes.html#manually-closing-streams // https://github.com/knex/knex/issues/2324 - res.on('close', () => { + const responseCloseHandler = () => { dbStream.end() dbStream.destroy() + } + + dbStream.on('close', () => { + res.removeListener('close', responseCloseHandler) }) + res.on('close', responseCloseHandler) const speckleObjStream = new SpeckleObjectsStream(isSimpleTextRequested(req)) diff --git a/packages/preview-service/src/server/routes/objects.ts b/packages/preview-service/src/server/routes/objects.ts index 7cfd4bd35..bd6e09225 100644 --- a/packages/preview-service/src/server/routes/objects.ts +++ b/packages/preview-service/src/server/routes/objects.ts @@ -41,12 +41,18 @@ const objectsRouterFactory = () => { streamId: req.params.streamId, objectId: req.params.objectId }) + // https://knexjs.org/faq/recipes.html#manually-closing-streams // https://github.com/knex/knex/issues/2324 - res.on('close', () => { + const responseCloseHandler = () => { dbStream.end() dbStream.destroy() + } + + dbStream.on('close', () => { + res.removeListener('close', responseCloseHandler) }) + res.on('close', responseCloseHandler) const speckleObjStream = new SpeckleObjectsStream(isSimpleTextRequested(req)) const gzipStream = zlib.createGzip() diff --git a/packages/server/modules/core/rest/diffDownload.ts b/packages/server/modules/core/rest/diffDownload.ts index 900988ccc..309bd93c1 100644 --- a/packages/server/modules/core/rest/diffDownload.ts +++ b/packages/server/modules/core/rest/diffDownload.ts @@ -94,12 +94,18 @@ export default (app: Application) => { streamId: req.params.streamId, objectIds: childrenChunk }) + // https://knexjs.org/faq/recipes.html#manually-closing-streams // https://github.com/knex/knex/issues/2324 - res.on('close', () => { + const responseCloseHandler = () => { dbStream.end() dbStream.destroy() + } + + dbStream.on('close', () => { + res.removeListener('close', responseCloseHandler) }) + res.on('close', responseCloseHandler) await new Promise((resolve, reject) => { dbStream.once('end', resolve) diff --git a/packages/server/modules/core/rest/download.ts b/packages/server/modules/core/rest/download.ts index 34e484529..e77e0bd83 100644 --- a/packages/server/modules/core/rest/download.ts +++ b/packages/server/modules/core/rest/download.ts @@ -63,12 +63,19 @@ export default (app: express.Express) => { streamId: req.params.streamId, objectId: req.params.objectId }) + // https://knexjs.org/faq/recipes.html#manually-closing-streams // https://github.com/knex/knex/issues/2324 - res.on('close', () => { + const responseCloseHandler = () => { dbStream.end() dbStream.destroy() + } + + dbStream.on('close', () => { + res.removeListener('close', responseCloseHandler) }) + res.on('close', responseCloseHandler) + const speckleObjStream = new SpeckleObjectsStream(simpleText) const gzipStream = zlib.createGzip()