using ZB.MOM.WW.OtOpcUa.Commons.Messages.Deploy; namespace ZB.MOM.WW.OtOpcUa.Runtime.Communication; /// /// Posts this node's deployment acknowledgment to central over the mesh_transport.v1 /// command plane (mesh gRPC command plane, Phase 1B). The seam /// uses under MeshTransport:Mode = Grpc, in place of /// the node-local DistributedPubSub publish it uses under Dps. /// /// /// /// One ack per node per dispatch. Whatever the implementation does about redundancy, it /// posts to one central endpoint at a time rather than fanning out — the semantic of the /// one-ack-per-node-per-dispatch semantic the deploy coordinator counts on. /// This is defence in depth, not a correctness dependency: the coordinator counts acks /// in a NodeId-keyed dictionary behind an expected-set membership guard /// (ConfigPublishCoordinator.HandleAck), so a duplicate from one node overwrites its own /// entry and cannot inflate the count or seal a deployment early. What fan-out would actually /// cost is duplicated work at central, doubled deploy-ack rows written, and a transport whose /// delivery count nobody can reason about — none of which is worth having. /// /// /// Fire-and-forget, and it never throws. The caller is an actor that discards the /// returned task, so an exception escaping here would become an unobserved task fault — the /// silent drop this migration exists to remove. An implementation reports failure by logging /// and returning, never by faulting the task. /// /// public interface IApplyAckSender { /// Posts to central, or logs why it could not be. /// The per-node apply acknowledgment. /// Cancels the in-flight call. /// /// A task that completes when the attempt finishes, successfully or not. It never faults — /// see the remarks. /// Task SendAsync(ApplyAck ack, CancellationToken cancellationToken = default); }