From 7bf3e5639e100f238e3f43f6e62a6b08f8c106e9 Mon Sep 17 00:00:00 2001 From: Vantz Stockwell Date: Sat, 21 Feb 2026 15:59:59 -0500 Subject: [PATCH] feat: Wire NATS command publishing for server commands and plugin installs - servers.service: sendCommand() now throws InternalServerErrorException on NATS failure instead of silently succeeding; returns { success, message } instead of the legacy { output } shape; adds NestJS Logger - plugins.service: installPlugin() dispatches plugin_install to corrosion.{license_id}.cmd.server after DB save; NATS failure is logged but non-fatal so the DB record is preserved regardless Co-Authored-By: Claude Opus 4.6 --- .../src/modules/plugins/plugins.service.ts | 16 +++++++++++++++- .../src/modules/servers/servers.service.ts | 14 +++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/backend-nest/src/modules/plugins/plugins.service.ts b/backend-nest/src/modules/plugins/plugins.service.ts index a8f3aec..03308d0 100644 --- a/backend-nest/src/modules/plugins/plugins.service.ts +++ b/backend-nest/src/modules/plugins/plugins.service.ts @@ -45,7 +45,21 @@ export class PluginsService { is_loaded: false, }); - return this.pluginRegistryRepo.save(plugin); + const saved = await this.pluginRegistryRepo.save(plugin); + + try { + await this.natsService.publish(`corrosion.${licenseId}.cmd.server`, { + action: 'plugin_install', + plugin_name: dto.plugin_name, + umod_slug: dto.umod_slug, + timestamp: new Date().toISOString(), + }); + this.logger.log(`Plugin install dispatched for ${dto.plugin_name} on license ${licenseId}`); + } catch (err) { + this.logger.error(`Failed to dispatch plugin install for ${dto.plugin_name} on license ${licenseId}: ${(err as Error).message}`); + } + + return saved; } async uninstallPlugin(licenseId: string, pluginId: string): Promise { diff --git a/backend-nest/src/modules/servers/servers.service.ts b/backend-nest/src/modules/servers/servers.service.ts index 6c1417e..5643120 100644 --- a/backend-nest/src/modules/servers/servers.service.ts +++ b/backend-nest/src/modules/servers/servers.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { Injectable, NotFoundException, InternalServerErrorException, Logger } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { ServerConnection } from '../../entities/server-connection.entity'; @@ -9,6 +9,8 @@ import { DeployServerDto } from './dto/deploy-server.dto'; @Injectable() export class ServersService { + private readonly logger = new Logger(ServersService.name); + constructor( @InjectRepository(ServerConnection) private readonly connectionRepo: Repository, @@ -60,8 +62,14 @@ export class ServersService { * Send a console command to the server via NATS */ async sendCommand(licenseId: string, command: string) { - await this.natsService.sendServerCommand(licenseId, 'command', { command }); - return { output: 'Command sent' }; + try { + await this.natsService.sendServerCommand(licenseId, 'command', { command }); + this.logger.log(`Console command dispatched for license ${licenseId}: ${command}`); + } catch (err) { + this.logger.error(`Failed to dispatch console command for license ${licenseId}: ${(err as Error).message}`); + throw new InternalServerErrorException('Failed to dispatch command to server'); + } + return { success: true, message: 'Command dispatched' }; } /**