c00603e2a4
The store-and-forward retry loop emits the per-attempt and terminal cached audit rows (ApiCallCached/DbWriteCached Attempted, CachedResolve) via CachedCallLifecycleBridge from a CachedCallAttemptContext, not from the script context. The ExecutionId rollout (Task 4) already threaded ExecutionId and SourceScript through this path; ParentExecutionId — the spawning inbound-API request's ExecutionId — was not, so those retry-loop rows had ParentExecutionId = null even for an inbound-API-routed run. Thread it additively as a sibling at every carry point ExecutionId passes through: - StoreAndForwardMessage gains ParentExecutionId (Guid?). - StoreAndForwardStorage adds a nullable parent_execution_id column via the same idempotent PRAGMA-probed ALTER TABLE migration; rows persisted by an older build read back null (back-compat). The defensive Guid.TryParse read helper (ParseExecutionId) is renamed ParseGuidColumn and reused for both columns so a corrupt value cannot abort the retry sweep. - StoreAndForwardService.EnqueueAsync gains an optional parentExecutionId param, stamped onto the buffered message and surfaced on the CachedCallAttemptContext built in the retry loop. - CachedCallAttemptContext gains ParentExecutionId. - CachedCallLifecycleBridge.BuildPacket sets AuditEvent.ParentExecutionId from the context, beside the existing ExecutionId. - IExternalSystemClient.CachedCallAsync / IDatabaseGateway.CachedWriteAsync gain an optional parentExecutionId param; ScriptRuntimeContext's CachedCall / CachedWrite helpers pass _parentExecutionId. All threading is additive — ParentExecutionId is Guid? everywhere, null for non-routed runs, and old buffered S&F rows still deserialize with the new field null.
62 lines
2.7 KiB
C#
62 lines
2.7 KiB
C#
using System.Data.Common;
|
|
using ScadaLink.Commons.Types;
|
|
|
|
namespace ScadaLink.Commons.Interfaces.Services;
|
|
|
|
/// <summary>
|
|
/// Interface for database access from scripts.
|
|
/// Implemented by ExternalSystemGateway, consumed by ScriptRuntimeContext.
|
|
/// </summary>
|
|
public interface IDatabaseGateway
|
|
{
|
|
/// <summary>
|
|
/// Returns an ADO.NET DbConnection (typically SqlConnection) from the named connection.
|
|
/// Connection pooling is managed by the underlying provider.
|
|
/// Caller is responsible for disposing.
|
|
/// </summary>
|
|
Task<DbConnection> GetConnectionAsync(
|
|
string connectionName,
|
|
CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Submits a SQL write to the store-and-forward engine for reliable delivery.
|
|
/// </summary>
|
|
/// <param name="trackedOperationId">
|
|
/// Audit Log #23 (M3): caller-supplied tracking id used as the
|
|
/// store-and-forward message id so the S&F retry loop can read it
|
|
/// back via <c>StoreAndForwardMessage.Id</c> and emit per-attempt /
|
|
/// terminal cached-write telemetry under the same id. Defaults to
|
|
/// <c>null</c> — when omitted the S&F engine mints a fresh GUID and no
|
|
/// M3 telemetry is correlated (pre-M3 caller behaviour).
|
|
/// </param>
|
|
/// <param name="executionId">
|
|
/// Audit Log #23 (ExecutionId Task 4): the originating script execution's
|
|
/// per-run correlation id. When the write is buffered on a transient
|
|
/// failure this is threaded onto the S&F message so the retry-loop
|
|
/// cached-write audit rows carry it. <c>null</c> when not threaded.
|
|
/// </param>
|
|
/// <param name="sourceScript">
|
|
/// Audit Log #23 (ExecutionId Task 4): the originating script identifier,
|
|
/// threaded onto the buffered S&F message alongside
|
|
/// <paramref name="executionId"/>. <c>null</c> when not known.
|
|
/// </param>
|
|
/// <param name="parentExecutionId">
|
|
/// Audit Log #23 (ParentExecutionId Task 6): the <c>ExecutionId</c> of the
|
|
/// inbound-API request that spawned the originating script execution.
|
|
/// When the write is buffered on a transient failure this is threaded onto
|
|
/// the S&F message alongside <paramref name="executionId"/> so the
|
|
/// retry-loop cached-write audit rows carry it. <c>null</c> for a
|
|
/// non-routed run.
|
|
/// </param>
|
|
Task CachedWriteAsync(
|
|
string connectionName,
|
|
string sql,
|
|
IReadOnlyDictionary<string, object?>? parameters = null,
|
|
string? originInstanceName = null,
|
|
CancellationToken cancellationToken = default,
|
|
TrackedOperationId? trackedOperationId = null,
|
|
Guid? executionId = null,
|
|
string? sourceScript = null,
|
|
Guid? parentExecutionId = null);
|
|
}
|