From ac4f1291b402e4e83d0ea7f2cc0fb59f22a9fdd4 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Tue, 4 Feb 2025 14:45:10 -0500 Subject: [PATCH 1/3] fix(api): change default execa opts in pm2 service --- api/src/unraid-api/cli/pm2.service.ts | 2 ++ api/src/unraid-api/cli/status.command.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/api/src/unraid-api/cli/pm2.service.ts b/api/src/unraid-api/cli/pm2.service.ts index a9ed9ffe62..aff78b19fc 100644 --- a/api/src/unraid-api/cli/pm2.service.ts +++ b/api/src/unraid-api/cli/pm2.service.ts @@ -40,6 +40,8 @@ export class PM2Service { */ async run(context: CmdContext, ...args: string[]) { const { tag, raw, ...execOptions } = context; + execOptions.extendEnv ??= false; + execOptions.shell ??= 'bash'; const runCommand = () => execa(PM2_PATH, [...args], execOptions satisfies Options); if (raw) { return runCommand(); diff --git a/api/src/unraid-api/cli/status.command.ts b/api/src/unraid-api/cli/status.command.ts index 4d29a8bbb4..b2aa20c2ed 100644 --- a/api/src/unraid-api/cli/status.command.ts +++ b/api/src/unraid-api/cli/status.command.ts @@ -9,7 +9,7 @@ export class StatusCommand extends CommandRunner { } async run(): Promise { await this.pm2.run( - { tag: 'PM2 Status', stdio: 'inherit', shell: 'bash', raw: true }, + { tag: 'PM2 Status', stdio: 'inherit', raw: true }, 'status', 'unraid-api' ); From 5fcb8f4068ff5ebf58a1eaa39d45c9534a1de18e Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Tue, 4 Feb 2025 14:49:45 -0500 Subject: [PATCH 2/3] feat(api): change pm2.run default log level to trace --- api/src/unraid-api/cli/log.service.ts | 6 ++++++ api/src/unraid-api/cli/pm2.service.ts | 3 +-- api/src/unraid-api/cli/status.command.ts | 6 +----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/api/src/unraid-api/cli/log.service.ts b/api/src/unraid-api/cli/log.service.ts index 7f9a26e009..54db45de46 100644 --- a/api/src/unraid-api/cli/log.service.ts +++ b/api/src/unraid-api/cli/log.service.ts @@ -48,4 +48,10 @@ export class LogService { this.logger.debug(message, ...optionalParams); } } + + trace(message: any, ...optionalParams: any[]): void { + if (this.shouldLog('trace')) { + this.logger.log(message, ...optionalParams); + } + } } diff --git a/api/src/unraid-api/cli/pm2.service.ts b/api/src/unraid-api/cli/pm2.service.ts index aff78b19fc..7ede53d256 100644 --- a/api/src/unraid-api/cli/pm2.service.ts +++ b/api/src/unraid-api/cli/pm2.service.ts @@ -48,8 +48,7 @@ export class PM2Service { } return runCommand() .then((result) => { - this.logger.debug(result.stdout); - this.logger.log(`Operation "${tag}" completed.`); + this.logger.trace(result.stdout); return result; }) .catch((result: Result) => { diff --git a/api/src/unraid-api/cli/status.command.ts b/api/src/unraid-api/cli/status.command.ts index b2aa20c2ed..31d7bd2759 100644 --- a/api/src/unraid-api/cli/status.command.ts +++ b/api/src/unraid-api/cli/status.command.ts @@ -8,10 +8,6 @@ export class StatusCommand extends CommandRunner { super(); } async run(): Promise { - await this.pm2.run( - { tag: 'PM2 Status', stdio: 'inherit', raw: true }, - 'status', - 'unraid-api' - ); + await this.pm2.run({ tag: 'PM2 Status', stdio: 'inherit', raw: true }, 'status', 'unraid-api'); } } From a4b79062be9854db31bf1c8fc526d8a393b5e5d9 Mon Sep 17 00:00:00 2001 From: Pujit Mehrotra Date: Tue, 4 Feb 2025 15:04:34 -0500 Subject: [PATCH 3/3] doc(api): add tsdoc for `pm2.run` --- api/src/unraid-api/cli/pm2.service.ts | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/api/src/unraid-api/cli/pm2.service.ts b/api/src/unraid-api/cli/pm2.service.ts index 7ede53d256..112b24044d 100644 --- a/api/src/unraid-api/cli/pm2.service.ts +++ b/api/src/unraid-api/cli/pm2.service.ts @@ -25,19 +25,21 @@ export class PM2Service { constructor(private readonly logger: LogService) {} // Type Overload: if raw is true, return an execa ResultPromise (which is a Promise with extra properties) + /** + * Executes a PM2 command with the specified context and arguments. + * Handles logging automatically (stdout -> trace, stderr -> error), unless the `raw` flag is + * set to true, in which case the caller must handle desired effects. + * + * @param context - Execa Options for command execution, such as a unique tag for logging + * and whether the result should be handled raw. + * @param args - The arguments to pass to the PM2 command. + * @returns ResultPromise\<@param context\> When raw is true + * @returns Promise\ When raw is false + */ run(context: T & { raw: true }, ...args: string[]): ResultPromise; - // Type Overload: if raw is false, return a plain Promise run(context: CmdContext & { raw?: false }, ...args: string[]): Promise; - /** - * Executes a PM2 command with the provided arguments and environment variables. - * - * @param context - An object containing a tag for logging purposes and optional environment variables (merging with current env). - * @param args - Arguments to pass to the PM2 command. Each arguement is escaped. - * @returns A promise that resolves to a Result object containing the command's output. - * Logs debug information on success and error details on failure. - */ async run(context: CmdContext, ...args: string[]) { const { tag, raw, ...execOptions } = context; execOptions.extendEnv ??= false; @@ -60,13 +62,13 @@ export class PM2Service { /** * Deletes the PM2 dump file. * - * This method removes the PM2 dump file located at `~/.pm2/dump.pm2`. + * This method removes the PM2 dump file located at `~/.pm2/dump.pm2` by default. * It logs a message indicating that the PM2 dump has been cleared. * * @returns A promise that resolves once the dump file is removed. */ async deleteDump(dumpFile = join(PM2_HOME, 'dump.pm2')) { await rm(dumpFile, { force: true }); - this.logger.log('PM2 dump cleared.'); + this.logger.trace('PM2 dump cleared.'); } }