From 6e1d12d3b826d6947f0bf36b89fbadaa6081fdec Mon Sep 17 00:00:00 2001 From: einhornimmond Date: Tue, 14 Oct 2025 08:28:45 +0200 Subject: [PATCH] log shutdown reasons --- .../1_0/resolver/AuthenticationResolver.ts | 5 +-- federation/src/index.ts | 8 ++++ shared/src/helper/BinaryData.ts | 10 ++++- shared/src/helper/index.ts | 3 +- shared/src/helper/onShutdown.ts | 43 +++++++++++++++++++ 5 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 shared/src/helper/onShutdown.ts diff --git a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts index fba153275..6712c47d5 100644 --- a/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts +++ b/federation/src/graphql/api/1_0/resolver/AuthenticationResolver.ts @@ -51,10 +51,9 @@ export class AuthenticationResolver { if (!openConnectionJwtPayload.url) { throw new Error(`invalid url of community with publicKey ${argsPublicKey.asHex()}`) } - methodLogger.debug(`vor DbFedCommunity.findOneByOrFail()...`, { publicKey: argsPublicKey.asHex() }) + methodLogger.debug(`before DbFedCommunity.findOneByOrFail()...`, { publicKey: argsPublicKey.asHex() }) const fedComA = await DbFedCommunity.findOneByOrFail({ publicKey: argsPublicKey.asBuffer() }) - methodLogger.debug(`nach DbFedCommunity.findOneByOrFail()...`, fedComA) - methodLogger.debug('fedComA', new FederatedCommunityLoggingView(fedComA)) + methodLogger.debug(`after DbFedCommunity.findOneByOrFail()...`, new FederatedCommunityLoggingView(fedComA)) if (!openConnectionJwtPayload.url.startsWith(fedComA.endPoint)) { throw new Error(`invalid url of community with publicKey ${argsPublicKey.asHex()}`) } diff --git a/federation/src/index.ts b/federation/src/index.ts index 4492f24fb..ad0df6b0f 100644 --- a/federation/src/index.ts +++ b/federation/src/index.ts @@ -6,6 +6,7 @@ import { getLogger } from 'log4js' // config import { CONFIG } from './config' import { LOG4JS_BASE_CATEGORY_NAME } from './config/const' +import { onShutdown, ShutdownReason } from 'shared' async function main() { // init logger @@ -27,6 +28,13 @@ async function main() { `GraphIQL available at ${CONFIG.FEDERATION_COMMUNITY_URL}/api/${CONFIG.FEDERATION_API}`, ) } + onShutdown(async (reason, details) => { + if (ShutdownReason.SIGINT === reason || ShutdownReason.SIGTERM === reason) { + logger.info(`graceful shutdown: ${reason}`) + } else { + logger.error(`crash: ${reason} ${details}`) + } + }) }) } diff --git a/shared/src/helper/BinaryData.ts b/shared/src/helper/BinaryData.ts index c21fad9dd..afffd5bfb 100644 --- a/shared/src/helper/BinaryData.ts +++ b/shared/src/helper/BinaryData.ts @@ -17,7 +17,13 @@ export class BinaryData { } logging.debug(`constructor() input type: ${typeof input}`) logging.debug(`constructor() input isBuffer: ${Buffer.isBuffer(input)}`) - logging.debug(`constructor() input: ${input}`) + if (typeof input === 'string') { + logging.debug(`constructor() input: ${input}`) + } else if (Buffer.isBuffer(input)) { + logging.debug(`constructor() input: ${input.toString('hex')}`) + } else { + logging.debug(`constructor() unexpected input type: ${typeof input}`) + } if (typeof input === 'string') { this.buf = Buffer.from(input, 'hex') this.hex = input @@ -38,6 +44,8 @@ export class BinaryData { } isSame(other: BinaryData): boolean { + logging.debug(`isSame() this: ${this.buf}`) + logging.debug(`isSame() other: ${other.buf}`) return this.buf.compare(other.buf) === 0 } } diff --git a/shared/src/helper/index.ts b/shared/src/helper/index.ts index 39f988ba4..9170aad49 100644 --- a/shared/src/helper/index.ts +++ b/shared/src/helper/index.ts @@ -1,2 +1,3 @@ export * from './updateField' -export * from './BinaryData' \ No newline at end of file +export * from './BinaryData' +export * from './onShutdown' \ No newline at end of file diff --git a/shared/src/helper/onShutdown.ts b/shared/src/helper/onShutdown.ts new file mode 100644 index 000000000..ff74699d8 --- /dev/null +++ b/shared/src/helper/onShutdown.ts @@ -0,0 +1,43 @@ +export enum ShutdownReason { + SIGINT = 'SIGINT', + SIGTERM = 'SIGTERM', + UNCAUGHT_EXCEPTION = 'UNCAUGHT_EXCEPTION', + UNCAUGHT_REJECTION = 'UNCAUGHT_REJECTION', +} + + +/** + * Setup graceful shutdown for the process + * @param gracefulShutdown will be called if process is terminated + */ +export function onShutdown(shutdownHandler: (reason: ShutdownReason, details?: string) => Promise) { + const signals: NodeJS.Signals[] = ['SIGINT', 'SIGTERM'] + signals.forEach(sig => { + process.on(sig, async () => { + await shutdownHandler(sig as ShutdownReason) + process.exit(0) + }) + }) + + process.on('uncaughtException', async (err, origin) => { + await shutdownHandler(ShutdownReason.UNCAUGHT_EXCEPTION, `${origin}: ${err}`) + process.exit(1) + }) + + process.on('unhandledRejection', async (reason, promise) => { + await shutdownHandler(ShutdownReason.UNCAUGHT_REJECTION, `${promise}: ${reason}`) + process.exit(1) + }) + + if (process.platform === "win32") { + const rl = require("readline").createInterface({ + input: process.stdin, + output: process.stdout, + }) + rl.on("SIGINT", () => { + process.emit("SIGINT" as any) + }) + } + + +} \ No newline at end of file