namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions; /// /// Abstraction over the Phase 6.1 resilience pipeline that wraps a single driver instance's /// capability calls (retry / circuit-breaker / in-flight accounting / tracker telemetry). The Runtime /// dispatch layer (DriverInstanceActor) consumes this interface instead of the concrete /// CapabilityInvoker so the actor assembly does NOT pull in /// ZB.MOM.WW.OtOpcUa.Core (which drags in Polly + driver hosting) — the same boundary /// rationale as . The fused Host binds a real invoker (built by /// ) per spawned driver; when none is supplied the /// dispatch layer uses , a genuine pass-through. /// /// /// The method shapes mirror CapabilityInvoker exactly so the concrete invoker satisfies /// this interface without adapters. Callers pass the resolved hostName per call (a /// multi-host driver resolves it from the tag reference via ; /// a single-host driver passes its ) so per-host breaker /// isolation + in-flight-depth accounting key on the right target. /// public interface IDriverCapabilityInvoker { /// Execute a value-returning capability call through the per-capability pipeline. /// Return type of the underlying driver call. /// The driver capability being executed. /// The resolved host name for pipeline keying + status tracking. /// The async function to execute (the raw driver-capability call). /// Cancellation token for the operation. /// The result of the underlying driver call. ValueTask ExecuteAsync( DriverCapability capability, string hostName, Func> callSite, CancellationToken cancellationToken); /// Execute a void-returning capability call through the per-capability pipeline. /// The driver capability being executed. /// The resolved host name for pipeline keying + status tracking. /// The async function to execute (the raw driver-capability call). /// Cancellation token for the operation. /// A task that represents the asynchronous operation. ValueTask ExecuteAsync( DriverCapability capability, string hostName, Func callSite, CancellationToken cancellationToken); /// /// Execute a call honoring idempotence semantics — when /// is false, retries are disabled regardless of the /// configured policy; when true, the call runs through the Write pipeline which may /// retry if the tier configuration permits. The current production default is false /// (R2-02/S-8): DriverInstanceActor.HandleWriteAsync passes isIdempotent: false so a /// command-shaped write is never replayed; per-tag opt-in via /// is the unshipped forward path. /// /// Return type of the underlying driver write call. /// The resolved host name for pipeline keying + status tracking. /// Whether the write operation is safe to retry. /// The async function to execute (the raw driver write call). /// Cancellation token for the operation. /// The result of the underlying driver write call. ValueTask ExecuteWriteAsync( string hostName, bool isIdempotent, Func> callSite, CancellationToken cancellationToken); } /// /// Pass-through that invokes the call site directly with /// NO pipeline — no timeout, retry, breaker, or telemetry. Bound when the dispatch layer is /// constructed without a real invoker (unit tests, the F7 skeleton path, admin-only nodes that /// never run drivers). Keeps behavior byte-for-byte identical to a raw driver call so existing /// dispatch-layer tests are unaffected by the resilience wiring. /// public sealed class NullDriverCapabilityInvoker : IDriverCapabilityInvoker { /// The shared singleton instance. public static readonly NullDriverCapabilityInvoker Instance = new(); private NullDriverCapabilityInvoker() { } /// public ValueTask ExecuteAsync( DriverCapability capability, string hostName, Func> callSite, CancellationToken cancellationToken) => callSite(cancellationToken); /// public ValueTask ExecuteAsync( DriverCapability capability, string hostName, Func callSite, CancellationToken cancellationToken) => callSite(cancellationToken); /// public ValueTask ExecuteWriteAsync( string hostName, bool isIdempotent, Func> callSite, CancellationToken cancellationToken) => callSite(cancellationToken); }