From 3ee0e773a504871754c2ab924ca56b9c96677021 Mon Sep 17 00:00:00 2001 From: Attila Orosz Date: Wed, 1 Feb 2023 17:59:36 +0100 Subject: [PATCH 1/2] feat: add option to dispose scoped container --- src/SocketControllers.ts | 38 ++++++++-------- src/types/SocketControllersOptions.ts | 2 + test/functional/scoped-controllers.spec.ts | 50 +++++++++++++++++++++- 3 files changed, 70 insertions(+), 20 deletions(-) diff --git a/src/SocketControllers.ts b/src/SocketControllers.ts index 30ad9f9f..f36bfa0b 100644 --- a/src/SocketControllers.ts +++ b/src/SocketControllers.ts @@ -163,18 +163,18 @@ export class SocketControllers { ); if (connectedAction) { - this.executeAction(socket, controller, connectedAction); + void this.executeAction(socket, controller, connectedAction); } if (disconnectedAction) { socket.on('disconnect', () => { - this.executeAction(socket, controller, disconnectedAction); + void this.executeAction(socket, controller, disconnectedAction); }); } if (disconnectingAction) { socket.on('disconnecting', () => { - this.executeAction(socket, controller, disconnectingAction); + void this.executeAction(socket, controller, disconnectingAction); }); } @@ -187,12 +187,12 @@ export class SocketControllers { messages.push(ack); } - this.executeAction(socket, controller, messageAction, messageAction.options.name as string, messages); + void this.executeAction(socket, controller, messageAction, messageAction.options.name as string, messages); }); } } - private executeAction( + private async executeAction( socket: Socket, controller: HandlerMetadata, action: ActionMetadata, @@ -200,26 +200,26 @@ export class SocketControllers { data?: any[] ) { const parameters = this.resolveParameters(socket, controller.metadata, action.parameters || [], data); - try { - let container = this.container; - if (this.options.scopedContainerGetter) { - container = this.options.scopedContainerGetter( - this.collectScopedContainerParams(socket, action.type, eventName, data, controller.metadata.namespace) - ); - } + let container = this.container; + if (this.options.scopedContainerGetter) { + container = this.options.scopedContainerGetter( + this.collectScopedContainerParams(socket, action.type, eventName, data, controller.metadata.namespace) + ); + } + + try { const controllerInstance: any = container.get(controller.target); const actionResult = controllerInstance[action.methodName](...parameters); - Promise.resolve(actionResult) - .then(result => { - this.handleActionResult(socket, action, result, ResultType.EMIT_ON_SUCCESS); - }) - .catch(error => { - this.handleActionResult(socket, action, error, ResultType.EMIT_ON_FAIL); - }); + const result = await Promise.resolve(actionResult); + this.handleActionResult(socket, action, result, ResultType.EMIT_ON_SUCCESS); } catch (error: any) { this.handleActionResult(socket, action, error, ResultType.EMIT_ON_FAIL); } + + if (this.options.scopedContainerDisposer) { + this.options.scopedContainerDisposer(container); + } } private handleActionResult(socket: Socket, action: ActionMetadata, result: any, resultType: ResultType) { diff --git a/src/types/SocketControllersOptions.ts b/src/types/SocketControllersOptions.ts index e61b90d1..eb838ae4 100644 --- a/src/types/SocketControllersOptions.ts +++ b/src/types/SocketControllersOptions.ts @@ -9,6 +9,8 @@ export interface SocketControllersOptions { get(someClass: { new (...args: any[]): T } | Function): T; }; + scopedContainerDisposer?: (container: { get(someClass: { new (...args: any[]): T } | Function): T }) => void; + io?: Server; port?: number; diff --git a/test/functional/scoped-controllers.spec.ts b/test/functional/scoped-controllers.spec.ts index 5085e628..0998033c 100644 --- a/test/functional/scoped-controllers.spec.ts +++ b/test/functional/scoped-controllers.spec.ts @@ -2,7 +2,7 @@ import { createServer, Server as HttpServer } from 'http'; import { Server } from 'socket.io'; import { io, Socket } from 'socket.io-client'; import { SocketControllers } from '../../src/SocketControllers'; -import { Container, Inject, Service, Token } from 'typedi'; +import { Container, ContainerInstance, Inject, Service, Token } from "typedi"; import { SocketController } from '../../src/decorators/SocketController'; import { OnConnect } from '../../src/decorators/OnConnect'; import { ConnectedSocket } from '../../src/decorators/ConnectedSocket'; @@ -206,4 +206,52 @@ describe('Scoped controllers', () => { expect(testResult[1].messageArgs).toEqual(['args1']); expect(testResult[1].nspParams).toEqual({ test: 'string' }); }); + + it('container should be disposed', async () => { + const token = new Token('ADDITIONAL'); + + @Service({ global: true }) + class TestService {} + + @SocketController('/string') + @Service() + class TestController { + constructor(private testService: TestService, @Inject(token) public myAdditional: number) {} + + @OnConnect() + connected(@ConnectedSocket() socket: Socket) { + socket.emit('connected'); + } + + @OnMessage('test') + @EmitOnSuccess('done') + test() { + testResult.push(this.myAdditional); + } + } + + let container; + socketControllers = new SocketControllers({ + io: wsApp, + container: Container, + controllers: [TestController], + scopedContainerGetter: () => { + container = Container.of('test'); + container.set(token, 'test'); + return container; + }, + scopedContainerDisposer: (scopedContainer: ContainerInstance) => { + scopedContainer.reset({strategy: 'resetServices'}); + } + }); + wsClient = io(PATH_FOR_CLIENT + '/string', { reconnection: false, timeout: 5000, forceNew: true }); + + await waitForEvent(wsClient, 'connected'); + wsClient.emit('test'); + await waitForEvent(wsClient, 'done'); + + expect(Container.has(TestService)).toBe(true); + expect(container.has(token)).toBe(false); + expect(container.has(TestController)).toBe(false); + }); }); From 83d688157f8595a285c6d40065d72cc57a9f1035 Mon Sep 17 00:00:00 2001 From: Attila Orosz Date: Wed, 1 Feb 2023 18:01:34 +0100 Subject: [PATCH 2/2] prettier:fix --- test/functional/scoped-controllers.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/functional/scoped-controllers.spec.ts b/test/functional/scoped-controllers.spec.ts index 0998033c..9547511a 100644 --- a/test/functional/scoped-controllers.spec.ts +++ b/test/functional/scoped-controllers.spec.ts @@ -2,7 +2,7 @@ import { createServer, Server as HttpServer } from 'http'; import { Server } from 'socket.io'; import { io, Socket } from 'socket.io-client'; import { SocketControllers } from '../../src/SocketControllers'; -import { Container, ContainerInstance, Inject, Service, Token } from "typedi"; +import { Container, ContainerInstance, Inject, Service, Token } from 'typedi'; import { SocketController } from '../../src/decorators/SocketController'; import { OnConnect } from '../../src/decorators/OnConnect'; import { ConnectedSocket } from '../../src/decorators/ConnectedSocket'; @@ -241,8 +241,8 @@ describe('Scoped controllers', () => { return container; }, scopedContainerDisposer: (scopedContainer: ContainerInstance) => { - scopedContainer.reset({strategy: 'resetServices'}); - } + scopedContainer.reset({ strategy: 'resetServices' }); + }, }); wsClient = io(PATH_FOR_CLIENT + '/string', { reconnection: false, timeout: 5000, forceNew: true });