shoc-backend/SeaHaven.Services/Implementation/WorkOrderOpsHealthService.cs

82 lines
3.2 KiB
C#

using Data.SeaHavenIndustries;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using SeaHaven.Services.DTOs;
using SeaHaven.Services.Interfaces;
namespace SeaHaven.Services.Implementation
{
public class WorkOrderOpsHealthService : IWorkOrderOpsHealthService
{
private readonly ApplicationDbContext _db;
private readonly WorkOrderJobRunStateAccessor _runState;
private readonly bool _syncEnabled;
private readonly bool _ingestEnabled;
private readonly bool _legacyDeprecationEnabled;
private readonly string? _legacySunsetDate;
public WorkOrderOpsHealthService(
ApplicationDbContext db,
WorkOrderJobRunStateAccessor runState,
IOptions<WorkOrderOpsHealthOptions> options)
{
_db = db;
_runState = runState;
_syncEnabled = options.Value.SyncEnabled;
_ingestEnabled = options.Value.IngestEnabled;
_legacyDeprecationEnabled = options.Value.LegacyDeprecationEnabled;
_legacySunsetDate = options.Value.LegacySunsetDate;
}
public async Task<WorkOrderOpsHealthDto> GetHealthAsync(CancellationToken cancellationToken = default)
{
var since = DateTime.UtcNow.AddHours(-24);
var syncRejected = await _db.WorkOrderAuditLogs
.CountAsync(l => l.Action == "SyncRejected" && l.CreatedAt >= since, cancellationToken);
var fieldLocks = await _db.WorkOrderFieldLocks.CountAsync(cancellationToken);
var state = _runState.State;
var ledgerWeekRolled = await _db.WorkOrderWeekRolledLedgers
.MaxAsync(l => (DateTime?)l.ProcessedAt, cancellationToken);
return new WorkOrderOpsHealthDto
{
LastWeekRolledRunUtc = state.LastWeekRolledRunUtc ?? ledgerWeekRolled,
LastPastDueCacheRunUtc = state.LastPastDueCacheRunUtc,
LastWeekRolledError = state.LastWeekRolledError,
LastPastDueCacheError = state.LastPastDueCacheError,
SyncRejectedLast24h = syncRejected,
FieldLockCount = fieldLocks,
SyncEnabled = _syncEnabled,
IngestEnabled = _ingestEnabled,
LegacyDeprecationEnabled = _legacyDeprecationEnabled,
LegacySunsetDate = _legacySunsetDate,
CheckedAtUtc = DateTime.UtcNow
};
}
}
/// <summary>Options bridged from API configuration for health snapshots.</summary>
public class WorkOrderOpsHealthOptions
{
public bool SyncEnabled { get; set; } = true;
public bool IngestEnabled { get; set; } = true;
public bool LegacyDeprecationEnabled { get; set; }
public string? LegacySunsetDate { get; set; }
}
public class WorkOrderJobRunStateAccessor
{
public WorkOrderJobRunState State { get; } = new();
}
public class WorkOrderJobRunState
{
public DateTime? LastWeekRolledRunUtc { get; set; }
public DateTime? LastPastDueCacheRunUtc { get; set; }
public string? LastWeekRolledError { get; set; }
public string? LastPastDueCacheError { get; set; }
}
}