feat(admin): dispatch allowlisted maintenance jobs
CI and Deploy / test (push) Successful in 7m8s
CI and Deploy / deploy (push) Successful in 1m42s

This commit is contained in:
cesnimda
2026-09-01 16:53:54 +02:00
parent 3ec9ac1dad
commit 3b055b01f5
11 changed files with 328 additions and 8 deletions
@@ -18,8 +18,9 @@ public sealed class AdminSystemController : ControllerBase
private readonly ISummarizerService _summarizer;
private readonly IWebHostEnvironment _env;
private readonly IEmailSettingsResolver _emailSettings;
private readonly MaintenanceJobDispatcher _maintenanceJobs;
public AdminSystemController(IConfiguration cfg, AppPaths paths, JobTrackerContext db, ISummarizerService summarizer, IWebHostEnvironment env, IEmailSettingsResolver emailSettings)
public AdminSystemController(IConfiguration cfg, AppPaths paths, JobTrackerContext db, ISummarizerService summarizer, IWebHostEnvironment env, IEmailSettingsResolver emailSettings, MaintenanceJobDispatcher maintenanceJobs)
{
_cfg = cfg;
_paths = paths;
@@ -27,6 +28,7 @@ public sealed class AdminSystemController : ControllerBase
_summarizer = summarizer;
_env = env;
_emailSettings = emailSettings;
_maintenanceJobs = maintenanceJobs;
}
public sealed record StorageStatusDto(string DataRoot, string DbPath, bool DbExists, long? DbSizeBytes, int CompanyCount, int JobCount, int DeletedCount);
@@ -35,6 +37,7 @@ public sealed class AdminSystemController : ControllerBase
public sealed record RuntimeStatusDto(string Framework, string OSDescription, string ProcessArchitecture, string? MachineName);
public sealed record AuthStatusDto(bool Required, bool HasJwtKey, bool GoogleConfigured, bool GmailConfigured);
public sealed record CvBenchmarkStatusDto(string? IndexJson, string? ReportMarkdown, string RootPath, DateTimeOffset? LastUpdatedAtUtc);
public sealed record MaintenanceJobQueuedDto(string JobId, string Status, string? RunsUrl);
public sealed record SystemStatusDto(
string Environment,
string ContentRoot,
@@ -141,6 +144,27 @@ public sealed class AdminSystemController : ControllerBase
return Ok(new CvBenchmarkStatusDto(indexJson, reportMarkdown, _paths.CvBenchmarksRoot, lastUpdated == default ? null : new DateTimeOffset(DateTime.SpecifyKind(lastUpdated, DateTimeKind.Utc))));
}
[HttpGet("maintenance-jobs")]
public ActionResult<IReadOnlyList<MaintenanceJobDefinition>> GetMaintenanceJobs() => Ok(_maintenanceJobs.GetJobs());
[HttpPost("maintenance-jobs/{jobId}/runs")]
public async Task<ActionResult<MaintenanceJobQueuedDto>> RunMaintenanceJob(string jobId, CancellationToken cancellationToken)
{
var job = _maintenanceJobs.GetJobs().SingleOrDefault(candidate => candidate.Id == jobId);
if (job is null) return NotFound("Unknown maintenance job.");
if (!job.Available) return Problem("Maintenance job dispatch is not configured.", statusCode: StatusCodes.Status503ServiceUnavailable);
try
{
await _maintenanceJobs.DispatchAsync(jobId, cancellationToken);
return Accepted(new MaintenanceJobQueuedDto(jobId, "queued", job.RunsUrl));
}
catch (HttpRequestException)
{
return Problem("The maintenance runner did not accept the job. Try again or inspect Gitea Actions.", statusCode: StatusCodes.Status502BadGateway);
}
}
[HttpGet]
public async Task<ActionResult<SystemStatusDto>> Get(CancellationToken cancellationToken)
{