test(auditlog): assert ExecutionId threading hops; defensive Guid parse on S&F read

This commit is contained in:
Joseph Doherty
2026-05-21 15:27:37 -04:00
parent 6f5a35f222
commit 705ae95404
6 changed files with 195 additions and 17 deletions

View File

@@ -371,26 +371,45 @@ public class ExternalSystemClientTests
_httpClientFactory, _repository, NullLogger<ExternalSystemClient>.Instance,
storeAndForward: sf);
var result = await client.CachedCallAsync("TestAPI", "postData");
// Audit Log #23 (ExecutionId Task 4): a known execution id / source
// script so the gateway -> EnqueueAsync hop can be asserted below.
var executionId = Guid.NewGuid();
const string sourceScript = "ScriptActor:CheckPressure";
var result = await client.CachedCallAsync(
"TestAPI", "postData",
executionId: executionId, sourceScript: sourceScript);
Assert.True(result.WasBuffered);
var depth = await storage.GetBufferDepthByCategoryAsync();
Assert.Equal(1, depth[ScadaLink.Commons.Types.Enums.StoreAndForwardCategory.ExternalSystem]);
var (maxRetries, retryIntervalMs) = ReadBufferedRetrySettings(connStr);
Assert.Equal(7, maxRetries);
Assert.Equal((long)TimeSpan.FromSeconds(42).TotalMilliseconds, retryIntervalMs);
var buffered = ReadBufferedRetrySettings(connStr);
Assert.Equal(7, buffered.MaxRetries);
Assert.Equal((long)TimeSpan.FromSeconds(42).TotalMilliseconds, buffered.RetryIntervalMs);
// ExecutionId Task 4: the gateway must forward executionId / sourceScript
// into EnqueueAsync, and the S&F layer must persist them on the
// sf_messages row so the retry loop can stamp the right provenance.
Assert.Equal(executionId, buffered.ExecutionId);
Assert.Equal(sourceScript, buffered.SourceScript);
}
private static (int MaxRetries, long RetryIntervalMs) ReadBufferedRetrySettings(string connStr)
private static (int MaxRetries, long RetryIntervalMs, Guid? ExecutionId, string? SourceScript)
ReadBufferedRetrySettings(string connStr)
{
using var conn = new SqliteConnection(connStr);
conn.Open();
using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT max_retries, retry_interval_ms FROM sf_messages";
cmd.CommandText =
"SELECT max_retries, retry_interval_ms, execution_id, source_script FROM sf_messages";
using var reader = cmd.ExecuteReader();
Assert.True(reader.Read(), "expected exactly one buffered message");
var result = (reader.GetInt32(0), reader.GetInt64(1));
var result = (
reader.GetInt32(0),
reader.GetInt64(1),
reader.IsDBNull(2) ? (Guid?)null : Guid.Parse(reader.GetString(2)),
reader.IsDBNull(3) ? null : reader.GetString(3));
Assert.False(reader.Read(), "expected exactly one buffered message");
return result;
}
@@ -436,7 +455,7 @@ public class ExternalSystemClientTests
await client.CachedCallAsync("TestAPI", "postData");
var (maxRetries, _) = ReadBufferedRetrySettings(connStr);
var (maxRetries, _, _, _) = ReadBufferedRetrySettings(connStr);
// Must be the bounded S&F default, never 0 — a stored 0 would mean retry-forever.
Assert.Equal(99, maxRetries);
Assert.NotEqual(0, maxRetries);