fix(grpc): typed alarm-feed overflow, memoized alarm snapshot, cancellable stream writes, uniform reply correlation id
- StreamAlarms: slow subscribers are completed with AlarmFeedSubscriberOverflowException and surface as ResourceExhausted (like a StreamEvents overflow) instead of warning-with-stack + Unavailable. - GatewayAlarmMonitor.StreamAsync reuses the memoized alarm-set projection instead of cloning the whole set under the broadcast lock per attach; the prefix filter runs outside the lock. - StreamEvents/StreamAlarms pass the call token to response writes; a write failure after client cancel maps to Cancelled without a warning. - Every MxCommandReply.correlation_id now echoes the request's client_correlation_id (previously only constraint-denied replies did; normal replies leaked the internal envelope id).
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
namespace ZB.MOM.WW.MxGateway.Server.Alarms;
|
||||
|
||||
/// <summary>
|
||||
/// Completes an alarm-feed subscriber that fell behind its bounded queue and was dropped.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A typed exception rather than a bare <see cref="InvalidOperationException"/> so the gRPC
|
||||
/// layer can map it to <c>ResourceExhausted</c> — the status a <c>StreamEvents</c> overflow
|
||||
/// carries — without treating a slow client as a gateway failure (an unrecognized exception is
|
||||
/// logged as a warning with its stack and surfaced as <c>Unavailable</c>). The remedy is the
|
||||
/// same as for an event-stream overflow: reconnect, which re-snapshots the alarm set.
|
||||
/// </remarks>
|
||||
public sealed class AlarmFeedSubscriberOverflowException : Exception
|
||||
{
|
||||
/// <summary>The message every dropped subscriber is completed with.</summary>
|
||||
public const string DefaultMessage =
|
||||
"Alarm feed subscriber fell behind and was dropped; reconnect to re-snapshot.";
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AlarmFeedSubscriberOverflowException"/> class.</summary>
|
||||
public AlarmFeedSubscriberOverflowException()
|
||||
: base(DefaultMessage)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AlarmFeedSubscriberOverflowException"/> class.</summary>
|
||||
/// <param name="message">The error message.</param>
|
||||
public AlarmFeedSubscriberOverflowException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AlarmFeedSubscriberOverflowException"/> class.</summary>
|
||||
/// <param name="message">The error message.</param>
|
||||
/// <param name="innerException">The exception that caused this one.</param>
|
||||
public AlarmFeedSubscriberOverflowException(string message, Exception innerException)
|
||||
: base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user