/* ========================================================================
* Copyright (c) 2005-2025 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
namespace Opc.Ua.Client
{
///
/// Context provided by the session to the
/// . Decouples the engine from the
/// Session implementation, providing only the services and state the
/// engine needs to operate the publish loop.
///
public interface ISubscriptionEngineContext
{
///
/// The current session ID. Used to validate publish responses
/// belong to the current session.
///
NodeId SessionId { get; }
///
/// Whether the session is currently in a reconnecting state.
/// Publish responses received during reconnect should be
/// discarded or deferred.
///
bool Reconnecting { get; }
///
/// Whether the session is currently connected to the server.
///
bool Connected { get; }
///
/// Whether the session is in the process of closing.
///
bool Closing { get; }
///
/// Whether the session keep-alive has stopped (i.e. the
/// session is treated as lost). When true, additional publish
/// requests should be skipped to avoid spawning excessive
/// tasks that will only fail.
///
bool KeepAliveStopped { get; }
///
/// The UTC time of the last successful keep-alive. Useful for
/// diagnostic logging when is
/// true.
///
DateTime LastKeepAliveTime { get; }
///
/// Whether the session has been disposed. The engine should
/// stop processing if this is true.
///
bool Disposed { get; }
///
/// Whether subscriptions should be deleted from the server
/// when the session is closed.
///
bool DeleteSubscriptionsOnClose { get; }
///
/// The operation timeout for publish requests in milliseconds.
///
int OperationTimeout { get; }
///
/// The current server state as known by the session.
///
ServerState ServerState { get; }
///
/// The diagnostics mask to include in publish request headers.
///
DiagnosticsMasks ReturnDiagnostics { get; }
///
/// Telemetry context for logging and metrics.
///
ITelemetryContext Telemetry { get; }
#if OPCUA_V1_CLIENT
///
/// The list of subscriptions managed by this session.
/// The engine uses this to look up target subscriptions
/// from publish responses.
///
IReadOnlyList Subscriptions { get; }
#endif
///
/// Send a Publish request to the server.
///
/// The request header.
/// Subscription acknowledgements
/// to send with this request.
/// Cancellation token.
/// The publish response.
ValueTask PublishAsync(
RequestHeader requestHeader,
ArrayOf acknowledgements,
CancellationToken ct = default);
///
/// Transfer subscriptions to this session.
///
/// The request header.
/// IDs of subscriptions to
/// transfer.
/// Whether to send initial
/// values for monitored items.
/// Cancellation token.
/// The transfer response.
ValueTask TransferSubscriptionsAsync(
RequestHeader? requestHeader,
ArrayOf subscriptionIds,
bool sendInitialValues,
CancellationToken ct = default);
///
/// Delete subscriptions on the server.
///
/// The request header.
/// IDs of subscriptions to
/// delete.
/// Cancellation token.
/// The delete response.
ValueTask DeleteSubscriptionsAsync(
RequestHeader? requestHeader,
ArrayOf subscriptionIds,
CancellationToken ct = default);
///
/// Raise keep-alive notification on the session, indicating
/// the server is alive and responsive.
///
/// Current server state.
/// Timestamp of the response.
void OnKeepAlive(ServerState serverState, DateTime timestamp);
///
/// Raise a publish error event on the session.
///
/// The error that occurred.
/// The subscription ID
/// associated with the error.
/// The sequence number of the
/// failed notification.
void OnPublishError(
ServiceResult error,
uint subscriptionId,
uint sequenceNumber);
#if OPCUA_V1_CLIENT
///
/// Raise a publish notification event on the session.
///
/// The subscription that received
/// the notification.
/// The notification event args.
void OnPublishNotification(
Subscription subscription,
NotificationEventArgs notification);
#endif
///
/// Notify the session that a keep-alive error was detected,
/// which may trigger a reconnect.
///
/// The keep-alive error.
void OnKeepAliveError(ServiceResult error);
///
/// Track the start of an async publish request for diagnostics.
///
/// The task representing the request.
/// The diagnostics activity, if any.
/// The request handle.
/// The request type identifier.
void AsyncRequestStarted(
Task task,
Activity? activity,
uint requestHandle,
uint requestTypeId);
///
/// Track the completion of an async publish request.
///
/// The completed task.
/// The request handle.
/// The request type identifier.
void AsyncRequestCompleted(
Task task,
uint requestHandle,
uint requestTypeId);
///
/// The semaphore used to gate publish completions during
/// reconnect or transfer operations.
///
SemaphoreSlim ReconnectLock { get; }
///
/// Prepare acknowledgements to send with the next publish
/// request. Invokes the PublishSequenceNumbersToAcknowledge
/// event on the session, allowing callers to defer specific
/// acknowledgements.
///
/// The current list of
/// pending acknowledgements.
/// A tuple where toSend is the list to include in the
/// publish request and updatedPending replaces the pending
/// list.
(List toSend,
List updatedPending)
PrepareAcknowledgementsToSend(
List currentAcknowledgements);
///
/// Delete an orphaned subscription that was received in a
/// publish response but is not in the session's subscription
/// list.
///
/// The subscription ID to
/// delete.
ValueTask DeleteOrphanedSubscriptionAsync(uint subscriptionId);
///
/// The number of good outstanding publish requests that
/// are not defunct.
///
int GoodPublishRequestCount { get; }
///
/// Subscription service set client methods exposed by the
/// underlying session. Used by V2 engines to drive the full
/// subscription lifecycle (Create / Modify / SetPublishingMode
/// / Republish / Delete).
///
ISubscriptionServiceSetClientMethods SubscriptionServiceSet { get; }
///
/// Monitored item service set client methods exposed by the
/// underlying session. Used by V2 engines to drive monitored
/// item lifecycle (Create / Modify / Delete /
/// SetMonitoringMode / SetTriggering).
///
IMonitoredItemServiceSetClientMethods MonitoredItemServiceSet { get; }
///
/// Method service set client methods exposed by the underlying
/// session. Used by V2 engines to invoke server methods.
///
IMethodServiceSetClientMethods MethodServiceSet { get; }
}
}