fix(health): acked SendAsync transport — report-loss counter restore is live, not dead code
This commit is contained in:
@@ -140,10 +140,13 @@ public class HealthReportSender : BackgroundService
|
||||
var seq = Interlocked.Increment(ref _sequenceNumber);
|
||||
|
||||
// CollectReport atomically read-and-resets
|
||||
// the per-interval error counters via Interlocked.Exchange. If
|
||||
// the Send below throws, those counts are otherwise lost
|
||||
// forever — neither in the un-sent report nor in the now-zeroed
|
||||
// collector. Snapshot the freshly-collected report so that on a
|
||||
// the per-interval error counters via Interlocked.Exchange. The
|
||||
// transport is now an ACKED round-trip (SendAsync throws on
|
||||
// timeout/nack — review 01 [Medium]), so this restore path is live
|
||||
// rather than dead code. If the SendAsync below throws, those
|
||||
// counts are otherwise lost forever — neither in the un-sent
|
||||
// report nor in the now-zeroed collector. Snapshot the
|
||||
// freshly-collected report so that on a
|
||||
// transport failure we can atomically restore the counts back
|
||||
// into the collector via Interlocked.Add, so the next
|
||||
// successful report includes them. Concurrent increments
|
||||
@@ -157,7 +160,7 @@ public class HealthReportSender : BackgroundService
|
||||
|
||||
try
|
||||
{
|
||||
_transport.Send(reportWithSeq);
|
||||
await _transport.SendAsync(reportWithSeq, stoppingToken).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -4,13 +4,20 @@ namespace ZB.MOM.WW.ScadaBridge.HealthMonitoring;
|
||||
|
||||
/// <summary>
|
||||
/// Abstraction for sending health reports to central.
|
||||
/// In production, implemented via Akka remoting (Tell, fire-and-forget).
|
||||
/// In production, implemented over Akka ClusterClient with an acked round-trip
|
||||
/// (review 01 [Medium]): the transport Asks and awaits a
|
||||
/// <see cref="SiteHealthReportAck"/>, so a lost/rejected report surfaces as a
|
||||
/// fault the sender can observe (and its per-interval counter-restore fires).
|
||||
/// </summary>
|
||||
public interface IHealthReportTransport
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends a health report to central (fire-and-forget).
|
||||
/// Sends a health report to central and completes only once central has
|
||||
/// acknowledged processing. MUST THROW on non-delivery (Ask timeout, actor
|
||||
/// system not started, or a not-accepted ack) — the sender's counter-restore
|
||||
/// path in <c>HealthReportSender</c> depends on that exception.
|
||||
/// </summary>
|
||||
/// <param name="report">The site health report to send.</param>
|
||||
void Send(SiteHealthReport report);
|
||||
/// <param name="cancellationToken">Cancels the in-flight send.</param>
|
||||
Task SendAsync(SiteHealthReport report, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user