a79d8282dc
- 15 Controller-Klassen ersetzen Minimal APIs in Program.cs - Repository Pattern mit Interfaces + Implementierungen (Project, Task, Activity, User) - AuthService verwendet jetzt IUserRepository statt direktem DbContext-Zugriff - SecurityHeadersMiddleware als eigenständige Middleware-Klasse - PathSecurityHelper als gemeinsamer Helper für Pfadvalidierung - DTOs in eigenem Namespace Nexus.Api.DTOs - EF-Entities in Nexus.Api.Data (vorher Nexus.Api.Domain) - Program.cs auf DI-Registrierung + Middleware reduziert - Alle 43 Endpoints unverändert erhalten - Build + 3/3 Tests erfolgreich
72 lines
2.9 KiB
C#
72 lines
2.9 KiB
C#
using Microsoft.AspNetCore.Mvc;
|
|
using Nexus.Api.Data;
|
|
using Nexus.Api.Integrations;
|
|
using Nexus.Api.Repositories;
|
|
using Nexus.Api.Services;
|
|
|
|
namespace Nexus.Api.Controllers;
|
|
|
|
[ApiController]
|
|
[Route("api/v1/operations")]
|
|
public class OperationsController(
|
|
IAgentRuntime runtime,
|
|
IAgentService agentService,
|
|
IProjectRepository projectRepo,
|
|
ITaskRepository taskRepo,
|
|
IActivityRepository activityRepo) : ControllerBase
|
|
{
|
|
[HttpGet("snapshot")]
|
|
public async Task<IResult> GetSnapshot(CancellationToken ct)
|
|
{
|
|
var runtimeTask = runtime.GetStatusAsync(ct);
|
|
var agentsTask = agentService.GetAgentsAsync(ct);
|
|
var projectsTask = projectRepo.GetAllAsync(ct);
|
|
var tasksTask = taskRepo.GetAllAsync(ct);
|
|
var activityTask = activityRepo.GetRecentAsync(20, ct);
|
|
await Task.WhenAll(runtimeTask, agentsTask, projectsTask, tasksTask, activityTask);
|
|
|
|
var tasks = tasksTask.Result;
|
|
var projects = projectsTask.Result;
|
|
var agents = agentsTask.Result;
|
|
var completedTasks = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Done));
|
|
|
|
var runtimeStatus = runtimeTask.Result;
|
|
var runtimeHealthy = runtimeStatus.Status == OperationalStatus.Online;
|
|
|
|
var lastIncident = tasks
|
|
.Where(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked))
|
|
.OrderByDescending(x => x.UpdatedAt)
|
|
.Select(x => new { TaskId = (Guid?)x.Id, Title = (string?)x.Title, Since = (DateTimeOffset?)x.UpdatedAt })
|
|
.FirstOrDefault();
|
|
|
|
var projectHealth = new
|
|
{
|
|
Online = projects.Count(x => x.Status == OperationalStatus.Online),
|
|
Offline = projects.Count(x => x.Status == OperationalStatus.Offline),
|
|
Degraded = projects.Count(x => x.Status == OperationalStatus.Degraded),
|
|
Unknown = projects.Count(x => x.Status == OperationalStatus.Unknown)
|
|
};
|
|
|
|
return Results.Ok(new
|
|
{
|
|
generatedAt = DateTimeOffset.UtcNow,
|
|
runtime = runtimeStatus,
|
|
models = Array.Empty<object>(),
|
|
runtimeHealthy,
|
|
metrics = new
|
|
{
|
|
activeAgents = agents.Count,
|
|
queuedTasks = tasks.Count - completedTasks,
|
|
successRate = tasks.Count == 0 ? 100 : Math.Round(completedTasks * 100d / tasks.Count, 1),
|
|
incidents = tasks.Count(x => x.State == TaskStateHelper.ToStateString(TaskState.Blocked))
|
|
},
|
|
lastIncident,
|
|
projectHealth,
|
|
agents = agents.Select(x => new { x.Id, x.Name, x.Role, x.Status, x.Model }),
|
|
projects = projects.Select(x => new { x.Id, x.Name, x.Status, x.Progress, x.UpdatedAt }),
|
|
tasks = tasks.Select(x => new { x.Id, x.Title, x.State, x.Priority, x.ProjectId, x.UpdatedAt }),
|
|
activity = activityTask.Result.Select(x => new { x.Id, x.Type, x.Message, at = x.CreatedAt })
|
|
});
|
|
}
|
|
}
|