diff --git a/package.json b/package.json index 6a76e52..6e2c18e 100644 --- a/package.json +++ b/package.json @@ -44,14 +44,15 @@ }, "devDependencies": { "@nodesecure/eslint-config": "^1.9.0", + "@openally/config.typescript": "^1.0.3", "@types/jest": "^29.5.12", + "c8": "^10.1.2", "dotenv": "^16.4.5", + "glob": "^11.0.0", "jest": "^29.7.0", "testcontainers": "^10.10.0", "ts-jest": "^29.2.4", - "typescript": "^5.5.4", "tsx": "^4.7.0", - "glob": "^11.0.0", - "c8": "^10.1.2" + "typescript": "^5.5.4" } } diff --git a/src/class/eventManagement/dispatcher.class.ts b/src/class/eventManagement/dispatcher.class.ts index 65e36c9..4776dee 100644 --- a/src/class/eventManagement/dispatcher.class.ts +++ b/src/class/eventManagement/dispatcher.class.ts @@ -108,20 +108,20 @@ export class Dispatcher extends EventEmit private backupDispatcherTransactionStore: TransactionStore<"dispatcher">; private backupIncomerTransactionStore: TransactionStore<"incomer">; - private transactionHandler: TransactionHandler; + private transactionHandler: TransactionHandler; private logger: Logger; private incomerChannelHandler: IncomerChannelHandler; private activeChannels = new Set(); private pingInterval: number; - private pingIntervalTimer: NodeJS.Timeout; + private pingIntervalTimer: NodeJS.Timeout | undefined; private checkLastActivityInterval: number; - private checkLastActivityIntervalTimer: NodeJS.Timeout; + private checkLastActivityIntervalTimer: NodeJS.Timeout | undefined; private resolveTransactionInterval: number; - private checkDispatcherStateInterval: NodeJS.Timeout; - private resetCheckLastActivityTimeout: NodeJS.Timeout; - private resolveTransactionsInterval: NodeJS.Timeout; + private checkDispatcherStateInterval: NodeJS.Timeout | undefined; + private resetCheckLastActivityTimeout: NodeJS.Timeout | undefined; + private resolveTransactionsInterval: NodeJS.Timeout | undefined; private idleTime: number; private minTimeout = 0; // Arbitrary value according to fastify default pluginTimeout @@ -288,6 +288,10 @@ export class Dispatcher extends EventEmit } public async initialize() { + if (!this.subscriber) { + throw new Error(`redis subscriber not available`); + } + await this.subscriber.subscribe(this.dispatcherChannelName); this.subscriber.on("message", (channel, message) => { this.handleMessages(channel, message).catch((error) => this.logger.error({ error: error.stack })); @@ -333,7 +337,7 @@ export class Dispatcher extends EventEmit this.eventsHandler.removeAllListeners(); this.removeAllListeners(); - await this.subscriber.unsubscribe( + await this.subscriber?.unsubscribe( this.dispatcherChannelName, ...this.incomerChannelHandler.channels.keys(), ...this.activeChannels.values() @@ -351,7 +355,7 @@ export class Dispatcher extends EventEmit try { parsedMessage = JSON.parse(message); } - catch (error) { + catch (error: any) { this.logger.error({ channel, error: error.message }); return; @@ -383,7 +387,7 @@ export class Dispatcher extends EventEmit await this.eventsHandler.handleEvents(channel, parsedMessage); } - catch (error) { + catch (error: any) { this.logger.error({ channel, message: parsedMessage, @@ -485,7 +489,7 @@ export class Dispatcher extends EventEmit dispatcherToRemove ? this.removeNonActives([dispatcherToRemove]) : () => void 0 ]); } - catch (error) { + catch (error: any) { this.logger.error({ error: error.stack }, `${this.selfProvidedUUID} failed while taking back the lead`); return; @@ -529,7 +533,7 @@ export class Dispatcher extends EventEmit const inactiveIncomers = await this.incomerStore.getNonActives(); - const toResolve = []; + const toResolve: Promise[] = []; let index = 0; for (const inactive of inactiveIncomers) { @@ -545,10 +549,10 @@ export class Dispatcher extends EventEmit .map(([transactionId]) => transactionId); if (recentPingTransactionKeys.length > 0) { - toResolve.push(Promise.all([ + toResolve.push(...[ this.incomerStore.updateIncomerState(inactive.providedUUID), transactionStore.deleteTransactions(recentPingTransactionKeys) - ])); + ]); inactiveIncomers.splice(index, 1); } @@ -563,7 +567,7 @@ export class Dispatcher extends EventEmit private async ping() { const incomers = await this.incomerStore.getIncomers(); - const pingToResolve = []; + const pingToResolve: Promise[] = []; const concernedIncomers: string[] = []; for (const incomer of incomers) { if (incomer === null) { @@ -615,14 +619,16 @@ export class Dispatcher extends EventEmit } private async removeNonActives(inactiveIncomers: RegisteredIncomer[]) { - const toHandle = []; + const toHandle: Promise[] = []; for (const inactive of inactiveIncomers) { - toHandle.push(Promise.all([ + toHandle.push(...[ this.incomerStore.deleteIncomer(inactive.providedUUID), - this.transactionHandler.resolveInactiveIncomerTransactions(inactive), - this.activeChannels.add(`${inactive.prefix ? `${inactive.prefix}-` : ""}${inactive.providedUUID}`) - ])); + this.transactionHandler.resolveInactiveIncomerTransactions(inactive) + ]); + this.activeChannels.add( + `${inactive.prefix ? `${inactive.prefix}-` : ""}${inactive.providedUUID}` + ); } await Promise.all(toHandle); @@ -845,7 +851,7 @@ export class Dispatcher extends EventEmit for (const incomer of concernedIncomers) { const relatedEvent = incomer.eventsSubscribe.find((subscribedEvent) => subscribedEvent.name === eventName); - if (!relatedEvent.horizontalScale && + if (relatedEvent && !relatedEvent.horizontalScale && filteredConcernedIncomers.find( (filteredConcernedIncomer) => filteredConcernedIncomer.eventsSubscribe.find( (subscribedEvent) => subscribedEvent.name === relatedEvent.name && filteredConcernedIncomer.name === incomer.name diff --git a/src/class/eventManagement/dispatcher/events.class.ts b/src/class/eventManagement/dispatcher/events.class.ts index 05e2a5f..10f9bfa 100644 --- a/src/class/eventManagement/dispatcher/events.class.ts +++ b/src/class/eventManagement/dispatcher/events.class.ts @@ -110,7 +110,7 @@ export class EventsHandler extends EventEmitter { readonly dispatcherChannelName: string; #eventsValidationFn: eventsValidationFn; - #customValidationCbFn: customValidationCbFn; + #customValidationCbFn: customValidationCbFn | undefined; #logger: Logger; #standardLogFn: StandardLog; @@ -169,7 +169,7 @@ export class EventsHandler extends EventEmitter { try { this.dispatcherChannelMessagesSchemaValidation(event); } - catch (error) { + catch (error: any) { this.#logger.error(this.#standardLogFn({ ...event, redisMetadata: { diff --git a/src/class/eventManagement/dispatcher/incomer-channel.class.ts b/src/class/eventManagement/dispatcher/incomer-channel.class.ts index 49147dc..44109ee 100644 --- a/src/class/eventManagement/dispatcher/incomer-channel.class.ts +++ b/src/class/eventManagement/dispatcher/incomer-channel.class.ts @@ -57,7 +57,7 @@ export class IncomerChannelHandler< get( uuid: string ): ChannelMessages | null { - return this.channels.get(uuid); + return this.channels.get(uuid) ?? null; } async remove( @@ -67,7 +67,7 @@ export class IncomerChannelHandler< return; } - await this.subscriber.unsubscribe(uuid); + await this.subscriber?.unsubscribe(uuid); this.channels.delete(uuid); } } diff --git a/src/class/eventManagement/dispatcher/transaction-handler.class.ts b/src/class/eventManagement/dispatcher/transaction-handler.class.ts index 97d6846..c10a7be 100644 --- a/src/class/eventManagement/dispatcher/transaction-handler.class.ts +++ b/src/class/eventManagement/dispatcher/transaction-handler.class.ts @@ -221,7 +221,7 @@ export class TransactionHandler { return this.dispatcherTransactionStore.deleteTransaction(relatedPingTransactionId); } - const relatedIncomerPingTransaction = incomerPingTransactions.get(relatedPingTransactionId); + const relatedIncomerPingTransaction = incomerPingTransactions.get(relatedPingTransactionId)!; return Promise.all([ inactiveIncomerTransactionStore.deleteTransaction(relatedIncomerPingTransaction.redisMetadata.transactionId), @@ -336,7 +336,9 @@ export class TransactionHandler { relatedHandlerTransaction, relatedHandlerTransaction.redisMetadata.transactionId ), - incomerToRemoveTransactionStore.deleteTransaction(relatedHandlerTransaction.redisMetadata.transactionId) + incomerToRemoveTransactionStore.deleteTransaction( + relatedHandlerTransaction.redisMetadata.transactionId + ) ]); this.logger.debug( @@ -683,7 +685,7 @@ export class TransactionHandler { private async resolveSpreadTransactions(options: ResolveTransactions): Promise { const { incomers, backupIncomerTransactions, dispatcherTransactions } = options; - const toResolve = []; + const toResolve: any[] = []; const incomerStateToUpdate = new Set(); for (const [dispatcherTransactionId, dispatcherTransaction] of dispatcherTransactions.entries()) { @@ -738,7 +740,7 @@ export class TransactionHandler { } for (const filteredIncomerTransaction of filteredIncomerTransactions) { - const filteredIncomerTransactionId = filteredIncomerTransaction.redisMetadata.transactionId; + const filteredIncomerTransactionId = filteredIncomerTransaction.redisMetadata.transactionId!; if (dispatcherTransaction.redisMetadata.mainTransaction) { // Only in case of ping event @@ -794,7 +796,7 @@ export class TransactionHandler { private async resolveMainTransactions(options: ResolveTransactions) { const { incomers, backupIncomerTransactions, dispatcherTransactions } = options; - const toResolve = []; + const toResolve: Promise[] = []; const incomerStateToUpdate = new Set(); for (const incomer of incomers) { @@ -856,7 +858,7 @@ export class TransactionHandler { } } - toResolve.push([...incomerStateToUpdate.values()].map( + toResolve.push(...[...incomerStateToUpdate.values()].map( (incomerId) => this.incomerStore.updateIncomerState(incomerId)) ); diff --git a/src/class/eventManagement/externals.class.ts b/src/class/eventManagement/externals.class.ts index 2883379..a0edc9c 100644 --- a/src/class/eventManagement/externals.class.ts +++ b/src/class/eventManagement/externals.class.ts @@ -24,7 +24,6 @@ export class Externals { }); this.dispatcher = new Dispatcher({ - name: "pulsar", ...options, pingInterval: Number(process.env.MYUNISOFT_DISPATCHER_PING) || undefined, checkLastActivityInterval: Number(process.env.MYUNISOFT_DISPATCHER_ACTIVITY_CHECK) || undefined, diff --git a/src/class/eventManagement/incomer.class.ts b/src/class/eventManagement/incomer.class.ts index 9fa80d4..52a979b 100644 --- a/src/class/eventManagement/incomer.class.ts +++ b/src/class/eventManagement/incomer.class.ts @@ -145,8 +145,8 @@ export class Incomer < private checkTransactionsStateInterval: NodeJS.Timeout; private checkDispatcherStateTimeout: NodeJS.Timeout; private lastPingDate: number; - private eventsValidationFn: Map> | NestedValidationFunctions>; - private customValidationCbFn: (event: T) => void; + private eventsValidationFn: Map> | NestedValidationFunctions> | undefined; + private customValidationCbFn: ((event: T) => void) | undefined; public externals: Externals | undefined; @@ -557,7 +557,7 @@ export class Incomer < await this.handleIncomerMessages(channel, formattedMessage); } } - catch (error) { + catch (error: any) { this.logger.error({ channel, message: formattedMessage, error: error.stack }); } } @@ -588,7 +588,7 @@ export class Incomer < throw new Error("Unknown event"); }); } - catch (error) { + catch (error: any) { this.logger.error({ channel: "dispatcher", error: error.stack, @@ -770,29 +770,27 @@ export class Incomer < instance: "incomer" }); - const transactionToUpdate = []; + const transactionToUpdate: Promise[] = []; for (const [transactionId, transaction] of oldTransactions.entries()) { if (transaction.name === "REGISTER") { - transactionToUpdate.push([ - Promise.all([ - this.defaultIncomerTransactionStore.deleteTransaction(transactionId), - this.newTransactionStore.setTransaction({ - ...transaction, - redisMetadata: { - ...transaction.redisMetadata, - origin: this.providedUUID, - relatedTransaction: message.redisMetadata.transactionId, - published: true, - resolved: true - } - } as Transaction<"incomer">, transactionId) - ]) + transactionToUpdate.push(...[ + this.defaultIncomerTransactionStore.deleteTransaction(transactionId), + this.newTransactionStore.setTransaction({ + ...transaction, + redisMetadata: { + ...transaction.redisMetadata, + origin: this.providedUUID, + relatedTransaction: message.redisMetadata.transactionId, + published: true, + resolved: true + } + } as Transaction<"incomer">, transactionId) ]); continue; } - transactionToUpdate.push(Promise.all([ + transactionToUpdate.push(...[ this.defaultIncomerTransactionStore.deleteTransaction(transactionId), this.newTransactionStore.setTransaction({ ...transaction, @@ -801,7 +799,7 @@ export class Incomer < origin: this.providedUUID } }) - ])); + ]); } await Promise.all(transactionToUpdate); diff --git a/src/class/store/incomer.class.ts b/src/class/store/incomer.class.ts index d77fb52..bc58f19 100644 --- a/src/class/store/incomer.class.ts +++ b/src/class/store/incomer.class.ts @@ -93,7 +93,9 @@ export class IncomerStore extends KVPeer { const foundIncomers = await Promise.all(incomerKeys.map( (incomerKey) => this.getValue(incomerKey) )); - foundIncomers.forEach((incomer) => incomers.add(incomer)); + foundIncomers + .filter((incomer) => incomer !== null) + .forEach((incomer) => incomers.add(incomer)); } return incomers; @@ -101,7 +103,7 @@ export class IncomerStore extends KVPeer { getIncomer( incomerId: string - ): Promise { + ): Promise { return this.getValue( this.#buildIncomerKey(incomerId) ); diff --git a/src/class/store/transaction.class.ts b/src/class/store/transaction.class.ts index 791293c..04a6654 100644 --- a/src/class/store/transaction.class.ts +++ b/src/class/store/transaction.class.ts @@ -157,7 +157,7 @@ export class TransactionStore< transaction !== null && (transaction.redisMetadata && "transactionId" in transaction.redisMetadata) ) { - mappedTransactions.set(transaction.redisMetadata.transactionId, transaction); + mappedTransactions.set(transaction.redisMetadata.transactionId!, transaction); } } } diff --git a/src/utils/index.ts b/src/utils/index.ts index a124287..bc456e5 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -2,7 +2,7 @@ export * from "./defaultStandardLog.js"; export * from "./ajv.js"; export function handleLoggerMode( - mode: string + mode: string | undefined ): string { return (mode === "info" || mode === "debug" || mode === "warn" || mode === "silent") ? mode : "info"; } diff --git a/tsconfig.json b/tsconfig.json index 0a510f4..fd5adea 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,37 +1,19 @@ { - "compilerOptions": { - /* Base Options: */ - "target": "ES2022", - "module": "commonjs", - "allowJs": true, - "moduleResolution": "node", - "resolveJsonModule": true, - "esModuleInterop": true, - "moduleDetection": "force", - "isolatedModules": true, - "verbatimModuleSyntax": false, - - /* Strictness */ - "strict": false, - "noUncheckedIndexedAccess": false, - "noImplicitOverride": true, - - /* Others */ - "sourceMap": true, - "declaration": true, - "declarationMap": true, - "lib": ["es2022"], - "baseUrl": "./src", - "outDir": "./dist", - "types": ["jest", "node"], - "paths": { - "#src/*": ["./src/*"] - }, - "typeRoots": ["node_modules/@types", "./types"] - }, - "include": [ - "src/**/**/*.ts", - "./types" - ], - "exclude": ["node_modules", "example"] + "extends": "@openally/config.typescript/cjs", + "compilerOptions": { + "strictNullChecks": false, + "baseUrl": "./src", + "outDir": "./dist", + "types": [ + "jest", + "node" + ] + }, + "include": [ + "src" + ], + "exclude": [ + "node_modules", + "example" + ] }