using ScadaLink.Commons.Types;
namespace ScadaLink.Commons.Interfaces.Services;
///
/// Audit Log #23 (M3 Bundle E — Tasks E4/E5): site-side hook the
/// store-and-forward retry loop invokes after every cached-call attempt and
/// at terminal-state transitions, so the audit pipeline can emit
/// ApiCallCached/DbWriteCached per-attempt rows and the
/// CachedResolve terminal row under the original
/// .
///
///
///
/// The interface deliberately uses
/// rather than so the
/// S&F project does not need to depend on the audit vocabulary — the
/// bridge living in ScadaLink.AuditLog maps the outcome to the right
/// audit kind + status when materialising the CachedCallTelemetry
/// packet.
///
///
/// Best-effort contract (alog.md §7): implementations MUST swallow
/// internal failures rather than propagating to the S&F service — a
/// thrown observer must not be misclassified as a transient delivery
/// failure and must not corrupt the retry-count bookkeeping.
///
///
public interface ICachedCallLifecycleObserver
{
///
/// Called by the store-and-forward retry loop after every cached-call
/// delivery attempt. Receives the message's TrackedOperationId-bearing id,
/// the per-category channel discriminator, retry-count + last-error
/// context, and whether the outcome reached a terminal state.
///
Task OnAttemptCompletedAsync(CachedCallAttemptContext context, CancellationToken ct = default);
}
///
/// Per-attempt context handed to .
///
///
/// Tracking id parsed from the underlying StoreAndForwardMessage.Id.
///
///
/// Trust-boundary channel string — "ApiOutbound" for ExternalSystem
/// cached calls, "DbOutbound" for cached DB writes.
///
/// Human-readable target (system name / DB connection).
/// Site id that submitted the cached call.
/// Per-attempt outcome.
/// Number of retries performed so far (S&F bookkeeping).
/// Most recent error message (null on success).
/// Most recent HTTP status (null when not applicable).
/// When the underlying S&F message was first enqueued.
/// When this attempt completed.
/// Duration of the attempt in milliseconds (null when not measured).
/// Originating instance, when known.
///
/// Audit Log #23 (ExecutionId Task 4): the originating script execution's
/// per-run correlation id, threaded through the store-and-forward buffer from
/// the cached-call enqueue path. The audit bridge stamps it onto the
/// retry-loop ApiCallCached/DbWriteCached Attempted and
/// CachedResolve rows so they correlate with the rest of the run.
/// null for rows buffered before Task 4 (back-compat).
///
///
/// Audit Log #23 (ExecutionId Task 4): the originating script identifier,
/// threaded alongside so the retry-loop audit
/// rows carry the same SourceScript provenance the script-side cached
/// rows already do. null when not known.
///
///
/// Audit Log #23 (ParentExecutionId Task 6): the ExecutionId of the
/// inbound-API request that spawned the originating script execution,
/// threaded through the store-and-forward buffer alongside
/// . The audit bridge stamps it onto the
/// retry-loop ApiCallCached/DbWriteCached Attempted and
/// CachedResolve rows so they correlate back to the spawning run.
/// null for a non-routed run and for rows buffered before Task 6
/// (back-compat).
///
public sealed record CachedCallAttemptContext(
TrackedOperationId TrackedOperationId,
string Channel,
string Target,
string SourceSite,
CachedCallAttemptOutcome Outcome,
int RetryCount,
string? LastError,
int? HttpStatus,
DateTime CreatedAtUtc,
DateTime OccurredAtUtc,
int? DurationMs,
string? SourceInstanceId,
Guid? ExecutionId = null,
string? SourceScript = null,
Guid? ParentExecutionId = null);
///
/// Coarse outcome of one cached-call delivery attempt, observed from inside
/// the store-and-forward retry loop. The audit bridge maps this to the
/// ApiCallCached/DbWriteCached Attempted row and, when terminal,
/// the corresponding CachedResolve row.
///
public enum CachedCallAttemptOutcome
{
/// Attempt delivered successfully — terminal Delivered state.
Delivered,
/// Attempt failed transiently; another retry will follow.
TransientFailure,
/// Attempt returned permanent failure — terminal Parked state (S&F semantics).
PermanentFailure,
/// Retry budget exhausted — terminal Parked state.
ParkedMaxRetries,
}