feat(runtime): HistorianAdapter + PeerOpcUaProbe + DbHealthProbe actors (engine wiring tracked as F11/F12)
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
using Akka.Actor;
|
||||
using Akka.Event;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.Health;
|
||||
|
||||
/// <summary>
|
||||
/// Single-flight cached health probe against the ConfigDb. Reads cached state via
|
||||
/// <c>Ask<DbHealthStatus></c>; a single SELECT 1 runs at most every <c>RefreshInterval</c>.
|
||||
/// Consumed by both the host's <c>/health/ready</c> endpoint (Task 54) and
|
||||
/// <c>RedundancyStateActor</c>'s stale calc.
|
||||
/// </summary>
|
||||
public sealed class DbHealthProbeActor : ReceiveActor, IWithTimers
|
||||
{
|
||||
public static readonly TimeSpan RefreshInterval = TimeSpan.FromSeconds(5);
|
||||
|
||||
public sealed class GetStatus { public static readonly GetStatus Instance = new(); private GetStatus() { } }
|
||||
public sealed record DbHealthStatus(bool Reachable, DateTime AsOfUtc, string? LastError);
|
||||
public sealed class Tick { public static readonly Tick Instance = new(); private Tick() { } }
|
||||
|
||||
private readonly IDbContextFactory<OtOpcUaConfigDbContext> _dbFactory;
|
||||
private readonly ILoggingAdapter _log = Context.GetLogger();
|
||||
private DbHealthStatus _last = new(false, DateTime.MinValue, "not probed yet");
|
||||
|
||||
public ITimerScheduler Timers { get; set; } = null!;
|
||||
|
||||
public static Props Props(IDbContextFactory<OtOpcUaConfigDbContext> dbFactory) =>
|
||||
Akka.Actor.Props.Create(() => new DbHealthProbeActor(dbFactory));
|
||||
|
||||
public DbHealthProbeActor(IDbContextFactory<OtOpcUaConfigDbContext> dbFactory)
|
||||
{
|
||||
_dbFactory = dbFactory;
|
||||
Receive<GetStatus>(_ => Sender.Tell(_last));
|
||||
Receive<Tick>(_ => RunProbe());
|
||||
}
|
||||
|
||||
protected override void PreStart()
|
||||
{
|
||||
RunProbe();
|
||||
Timers.StartPeriodicTimer("probe", Tick.Instance, RefreshInterval);
|
||||
}
|
||||
|
||||
private void RunProbe()
|
||||
{
|
||||
try
|
||||
{
|
||||
using var db = _dbFactory.CreateDbContext();
|
||||
_ = db.Deployments.AsNoTracking().Take(1).ToList();
|
||||
_last = new DbHealthStatus(true, DateTime.UtcNow, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_last = new DbHealthStatus(false, DateTime.UtcNow, ex.Message);
|
||||
_log.Warning(ex, "DbHealthProbe: probe failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user