diff --git a/ee/app/license/server/license.internalService.ts b/ee/app/license/server/license.internalService.ts index 5d9d03381b36..8561cca6066b 100644 --- a/ee/app/license/server/license.internalService.ts +++ b/ee/app/license/server/license.internalService.ts @@ -32,41 +32,47 @@ export class LicenseService extends ServiceClassInternal implements ILicense { * So we list the services and nodes, and if there is more than * one, we inform the service that it should be disabled. */ - this.onEvent( - '$services.changed', - debounce(async () => { - if (hasLicense('scalability')) { - return; - } - - const services: { - name: string; - nodes: string[]; - }[] = await api.call('$node.services'); - - // Filter only the duplicated services - const duplicated = services.filter((service) => { - return service.name !== '$node' && service.nodes.length > 1; - }); - - if (!duplicated.length) { - return; - } - - const brokers: Record = Object.fromEntries( - duplicated.map((service) => { - // remove the first node from the list - const [, ...nodes] = service.nodes; - return [service.name, nodes]; - }), - ); - - const duplicatedServicesNames = duplicated.map((service) => service.name); - - // send shutdown signal to the duplicated services - api.broadcastToServices(duplicatedServicesNames, 'shutdown', brokers); - }, 1000), - ); + const shutdownServices = debounce(async () => { + if (hasLicense('scalability')) { + return; + } + + const services: { + name: string; + nodes: string[]; + }[] = await api.call('$node.services'); + + // Filter only the duplicated services + const duplicated = services.filter((service) => { + return service.name !== '$node' && service.nodes.length > 1; + }); + + if (!duplicated.length) { + return; + } + + const brokers: Record = Object.fromEntries( + duplicated.map((service) => { + // remove the first node from the list + const [, ...nodes] = service.nodes; + return [service.name, nodes]; + }), + ); + + const duplicatedServicesNames = duplicated.map((service) => service.name); + + // send shutdown signal to the duplicated services + api.broadcastToServices(duplicatedServicesNames, 'shutdown', brokers); + }, 1000); + + this.onEvent('$services.changed', async ({ localService }) => { + // since this is an internal service, we can ignore this event if the service that triggered is a local service. + // this will also prevent race conditions if a license is not in place when this process is starting up. + if (localService) { + return; + } + shutdownServices(); + }); } async started(): Promise { diff --git a/server/sdk/lib/Events.ts b/server/sdk/lib/Events.ts index 4d8dcc58c2e5..8b27ecd8a106 100644 --- a/server/sdk/lib/Events.ts +++ b/server/sdk/lib/Events.ts @@ -22,7 +22,7 @@ type ClientAction = 'inserted' | 'updated' | 'removed' | 'changed'; export type EventSignatures = { 'shutdown': (params: Record) => void; - '$services.changed': (info: unknown) => void; + '$services.changed': (info: { localService: boolean }) => void; 'accounts.login': (info: { userId: string; connection: ISocketConnection }) => void; 'accounts.logout': (info: { userId: string; connection: ISocketConnection }) => void; 'authorization.guestPermissions': (permissions: string[]) => void;