perf(dcl): batch subscribe/read/write seam, bounded reconnect, sharded subscriptions

This commit is contained in:
Joseph Doherty
2026-08-14 21:14:04 -04:00
parent ee193cd2bb
commit d15c5f02ea
25 changed files with 3131 additions and 324 deletions
@@ -6,7 +6,11 @@ namespace ZB.MOM.WW.ScadaBridge.DataConnectionLayer.Adapters;
/// <summary>Connection parameters resolved from the flat config dict.</summary>
public record MxGatewayConnectionOptions(
string Endpoint, string ApiKey, string ClientName, int WriteUserId,
bool UseTls, string? CaFile, string? ServerName, int ReadTimeoutMs);
bool UseTls, string? CaFile, string? ServerName, int ReadTimeoutMs,
// Maximum in-flight supervisory advise commands on the bulk-subscribe path when
// WriteUserId == 0 (the gateway worker has no BULK supervisory advise). Sourced from
// DataConnectionOptions.MxSupervisoryAdviseParallelism.
int SupervisoryAdviseParallelism = 16);
/// <summary>One advised-tag value change pushed from the gateway event stream.</summary>
public record MxValueUpdate(string TagPath, object? Value, QualityCode Quality, DateTimeOffset Timestamp);
@@ -17,6 +21,13 @@ public record MxReadOutcome(string TagPath, bool Success, object? Value, Quality
/// <summary>Per-tag write outcome.</summary>
public record MxWriteOutcome(string TagPath, bool Success, string? Error);
/// <summary>Per-tag outcome of a bulk subscribe (AddItem + Advise in one gateway command).</summary>
/// <param name="TagPath">The requested tag address.</param>
/// <param name="Success">Whether the item was added and advised.</param>
/// <param name="SubscriptionId">Gateway item handle (as a string) when successful.</param>
/// <param name="Error">Per-tag failure reason when not successful.</param>
public record MxSubscribeOutcome(string TagPath, bool Success, string? SubscriptionId, string? Error);
/// <summary>One node in a Galaxy browse level.</summary>
public record MxBrowseChild(string NodeId, string DisplayName, BrowseNodeClass NodeClass, bool HasChildren, string? DataType = null);
@@ -51,6 +62,25 @@ public interface IMxGatewayClient : IAsyncDisposable
/// <returns>A task that represents the asynchronous operation.</returns>
Task UnsubscribeAsync(string subscriptionId, CancellationToken ct = default);
/// <summary>
/// Adds and advises MANY tags in as few gateway commands as the worker allows —
/// ONE <c>SubscribeBulk</c> round trip in plain-advise mode, or one
/// <c>AddItemBulk</c> plus bounded-parallel supervisory advises when the connection
/// has no write-user context (the worker has no bulk supervisory advise).
/// Replaces the historical 2-RPC-per-tag AddItem + Advise pair.
/// </summary>
/// <param name="tagPaths">Tag addresses to subscribe.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>One outcome per requested tag path, in request order.</returns>
Task<IReadOnlyList<MxSubscribeOutcome>> SubscribeBulkAsync(
IReadOnlyList<string> tagPaths, CancellationToken ct = default);
/// <summary>UnAdvise + RemoveItem for many subscription ids in one gateway command.</summary>
/// <param name="subscriptionIds">Subscription ids previously returned by a subscribe call.</param>
/// <param name="ct">Cancellation token.</param>
/// <returns>A task that represents the asynchronous operation.</returns>
Task UnsubscribeBulkAsync(IReadOnlyList<string> subscriptionIds, CancellationToken ct = default);
/// <summary>Snapshot read of one or more tags (ReadBulk).</summary>
/// <param name="tagPaths">Tag addresses to read.</param>
/// <param name="ct">Cancellation token.</param>