From 485357c6dc926fc5ba2f1f4c775c4973e761fc4b Mon Sep 17 00:00:00 2001 From: Reviewer Date: Sun, 14 Jun 2026 11:30:17 +0200 Subject: [PATCH] review: error-handling for config file write + compose resource limits - AgentsController.SaveConfigFile: catch UnauthorizedAccessException and IOException instead of letting them bubble up unhandled; return clean 500 with logged message - compose.yaml: add deploy.resources.limits.memory and reservations.memory for api (512M/128M), web (128M/32M), postgres (256M/64M) --- backend/Controllers/AgentsController.cs | 27 +++++++++++++++++++++---- compose.yaml | 16 +++++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/backend/Controllers/AgentsController.cs b/backend/Controllers/AgentsController.cs index 0c3b605..01442e3 100644 --- a/backend/Controllers/AgentsController.cs +++ b/backend/Controllers/AgentsController.cs @@ -92,9 +92,28 @@ public class AgentsController( if (request.Content.Length > 500 * 1024) return Results.BadRequest(new { error = "Content exceeds maximum size of 500KB." }); - var result = await agentConfigService.SaveConfigFileAsync(id, fileName, request.Content, ct); - return result is null - ? Results.BadRequest(new { error = "Invalid filename or path." }) - : Results.Ok(new { result.FileName, result.Size, result.ModifiedAt }); + try + { + var result = await agentConfigService.SaveConfigFileAsync(id, fileName, request.Content, ct); + return result is null + ? Results.BadRequest(new { error = "Invalid filename or path." }) + : Results.Ok(new { result.FileName, result.Size, result.ModifiedAt }); + } + catch (UnauthorizedAccessException ex) + { + logger.LogError(ex, "Permission denied saving config file {FileName} for agent {AgentId}", fileName, id); + return Results.Problem( + title: "Permission denied", + detail: $"Cannot write config file '{fileName}' for agent '{id}'. The target path may be owned by a different user.", + statusCode: StatusCodes.Status500InternalServerError); + } + catch (IOException ex) + { + logger.LogError(ex, "I/O error saving config file {FileName} for agent {AgentId}", fileName, id); + return Results.Problem( + title: "File write error", + detail: $"Failed to write config file '{fileName}' for agent '{id}': {ex.Message}", + statusCode: StatusCodes.Status500InternalServerError); + } } } diff --git a/compose.yaml b/compose.yaml index 60768f8..f6fdc79 100644 --- a/compose.yaml +++ b/compose.yaml @@ -4,6 +4,12 @@ services: postgres: image: postgres:17-alpine restart: unless-stopped + deploy: + resources: + limits: + memory: 256M + reservations: + memory: 64M environment: POSTGRES_DB: ${POSTGRES_DB:-nexus} POSTGRES_USER: ${POSTGRES_USER:-nexus} @@ -28,6 +34,11 @@ services: context: ./backend restart: unless-stopped deploy: + resources: + limits: + memory: 512M + reservations: + memory: 128M restart_policy: condition: on-failure delay: 5s @@ -80,6 +91,11 @@ services: context: ./frontend restart: unless-stopped deploy: + resources: + limits: + memory: 128M + reservations: + memory: 32M restart_policy: condition: on-failure delay: 5s