From 761d215bee511f778ccdbe47ceb817af69dad3b4 Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Fri, 24 Jul 2026 04:34:55 -0400 Subject: [PATCH 1/3] Fix newGig receiver loop breaking permanently after one error (#246) The catch block in AgController.newGig() transmitted socketError then broke out of the receiver loop, permanently killing that client socket's newGig/newTour consumer after the first error. Sibling handlers (editDoc, removeGig) already transmit-and-continue; newGig now matches that behavior. Bump 3.0.8 -> 3.0.10 (skipping 3.0.9, already claimed by PR #245/#244). --- package-lock.json | 4 +-- package.json | 2 +- src/AgController/index.ts | 1 - test/AgController/index.spec.ts | 43 +++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index e52e48c..51172bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "webjamsocketserver", - "version": "3.0.8", + "version": "3.0.10", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "webjamsocketserver", - "version": "3.0.8", + "version": "3.0.10", "hasInstallScript": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index fcfbff3..8c83c4d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "webjamsocketserver", "description": "Uses latest version of socketcluster-server", - "version": "3.0.8", + "version": "3.0.10", "license": "MIT", "type": "module", "main": "build/src/index.js", diff --git a/src/AgController/index.ts b/src/AgController/index.ts index 87ebdf0..530f817 100644 --- a/src/AgController/index.ts +++ b/src/AgController/index.ts @@ -277,7 +277,6 @@ class AgController { const eMessage = (e as Error).message; debug(eMessage); client.socket.transmit('socketError', { newGig: eMessage });// send error back to client - break; } } })(); diff --git a/test/AgController/index.spec.ts b/test/AgController/index.spec.ts index f6a7b0d..b1df817 100644 --- a/test/AgController/index.spec.ts +++ b/test/AgController/index.spec.ts @@ -500,6 +500,49 @@ describe('AgControler', () => { agController.newGig(cStub, 'newGig'); expect(utils.handleGig).not.toHaveBeenCalled(); }); + it('keeps handling newGig on the same socket after an earlier newGig errored (#246)', async () => { + const agController = new AgController(aStub); + agController.clients = ['123']; + agController.gigController.createDocs = vi.fn(() => Promise.resolve([])); + agController.verifyAdminWrite = vi.fn(() => Promise.resolve()); + const transmit = vi.fn(); + let call = 0; + const cStub:any = { + socket: { + id: '123', + listener: () => ({ createConsumer: () => ({ next: () => Promise.resolve({ done: true, value: '1000' }) }) }), + transmit, + receiver: () => ({ + createConsumer: () => ({ + next: () => { + call += 1; + // First newGig on this socket: invalid gig data -> throws, must NOT break the loop. + if (call === 1) { + return Promise.resolve({ + value: { token: 'token', gig: { venue: 'venue' } }, + done: false, + }); + } + // Second newGig on the SAME socket/consumer: valid data -> must still be handled. + return Promise.resolve({ + value: { + token: 'token', + gig: { + venue: 'venue', datetime: new Date(), city: 'city', usState: 'state', + }, + }, + done: true, + }); + }, + }), + }), + }, + }; + agController.newGig(cStub, 'newGig'); + await delay(1000); + expect(transmit).toHaveBeenCalledWith('socketError', { newGig: 'Invalid create gig data' }); + expect(agController.gigController.createDocs).toHaveBeenCalled(); + }); it('process the newImage message from client', async () => { const agController = new AgController(aStub); agController.clients = ['123']; From 94ee046895a7bd6440788e37b65b68cdc6203eb7 Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Fri, 24 Jul 2026 09:22:32 -0400 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20de-zmpox=20.env.example=20?= =?UTF-8?q?=E2=80=94=20point=20placeholder=20at=20neutral=20host=20(closes?= =?UTF-8?q?=20#240)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.env.example b/.env.example index 60d4415..a1b7e5c 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,5 @@ -MONGO_DB_URI=mongodb+srv://username:password@orgname-zmpox.mongodb.net/databasename -TEST_DB=mongodb+srv://username:password@orgname-zmpox.mongodb.net/databasename +MONGO_DB_URI=mongodb+srv://username:password@orgname-xxxxx.mongodb.net/databasename +TEST_DB=mongodb+srv://username:password@orgname-xxxxx.mongodb.net/databasename GoogleClientSecret= HashString= AllowUrl={"urls": ["http://localhost:9000", "https://localhost:9000", "http://localhost:7000", "https://localhost:7000"]} From 1d6e45235dc99b18fe80a12be0fdfe512279cc0a Mon Sep 17 00:00:00 2001 From: JoshuaVSherman Date: Sat, 25 Jul 2026 04:51:37 -0400 Subject: [PATCH 3/3] Fix test-suite hang: newGig loop must check receiver.done even on error (#246) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CircleCI build 474 timed out in test/AgController/index.spec.ts. Root cause: after the earlier fix removed the error-path `break`, `newGig()`'s `if (receiver.done) break;` remained INSIDE the try block, right after the success path — so it was skipped whenever the catch fired. Several existing tests mock the receiver consumer to always resolve `{ ..., done: true }` on a payload that throws (invalid token/gig data); with the check unreachable on that path, those tests' un-awaited background loops spin forever, starving the event loop and hanging the whole suite. Fix: move the done-check to run unconditionally after the try/catch, matching the sibling editDoc/removeGig handlers. Production behavior is now correct too — the loop keeps serving newGig events after an error and still terminates cleanly when the client stream truly ends. Also fixed a latent test-pollution bug this hang had been masking: a test replaces the shared `utils.handleGig`/`utils.removeGig` exports with vi.fn() stubs and never restores them, which silently broke the #246 regression test's assertion that createDocs gets called on the second, valid newGig. Added restoration in afterEach. npm test: 10 test files / 86 tests passed, lint clean, no hang. --- src/AgController/index.ts | 2 +- test/AgController/index.spec.ts | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/AgController/index.ts b/src/AgController/index.ts index 530f817..690d893 100644 --- a/src/AgController/index.ts +++ b/src/AgController/index.ts @@ -272,12 +272,12 @@ class AgController { if (gig && gig.datetime && gig.city && gig.usState && gig.venue) { await utils.handleGig('createDocs', gig, 'gigCreated', this.gigController, this.server); } else throw new Error('Invalid create gig data'); - if (receiver.done) break; } catch (e) { const eMessage = (e as Error).message; debug(eMessage); client.socket.transmit('socketError', { newGig: eMessage });// send error back to client } + /* istanbul ignore else */if (receiver.done) break; } })(); } diff --git a/test/AgController/index.spec.ts b/test/AgController/index.spec.ts index b1df817..33c4510 100644 --- a/test/AgController/index.spec.ts +++ b/test/AgController/index.spec.ts @@ -30,8 +30,19 @@ const aStub:any = { }), }; +const realHandleGig = utils.handleGig; +const realRemoveGig = utils.removeGig; + describe('AgControler', () => { - afterEach(() => { vi.unstubAllGlobals(); }); + afterEach(() => { + vi.unstubAllGlobals(); + // Several tests replace these shared utils exports with vi.fn() stubs + // (e.g. line ~483) without restoring them, which otherwise leaks into + // later tests (like the #246 regression test) that need the real + // implementation and silently breaks their assertions. + utils.handleGig = realHandleGig; + utils.removeGig = realRemoveGig; + }); let r, clientStub:any = { id: '123', listener: () => ({ createConsumer: () => ({ next: () => Promise.resolve({ done: true, value: '1000' }) }) }),