fix(runtime): review findings — recursion-safe run cap, atomic detach counter, summary edge cases, per-row event-log fallback

This commit is contained in:
Joseph Doherty
2026-08-14 23:42:29 -04:00
parent b1de9dfdd4
commit 950c54c5fc
10 changed files with 626 additions and 42 deletions
@@ -149,6 +149,55 @@ public class ScriptRunSummaryRecorderTests
Assert.Contains($"{expectedTotal} completed", row.Message);
}
[Fact]
public async Task RunSpanningAFlushBoundary_StillReportsItsCompletionInTheNextWindow()
{
// A long run starts in window N and finishes in window N+1. Its completion is recorded
// against a FRESH counters object whose Started is 0 — so a flush filter keyed on
// Started/Failed/TimedOut alone would discard it, and the completion (plus its
// duration) would appear in NO summary row at all: window N reports a run that started
// and never finished, window N+1 reports nothing.
var recorder = new ScriptRunSummaryRecorder();
recorder.RecordStarted("Inst1", "Slow");
var firstLog = new FakeSiteEventLogger();
Assert.True(await recorder.FlushAsync(firstLog));
Assert.Equal("1 runs: 0 completed, 0 failed, 0 timed out across 1 scripts",
firstLog.OfType("script").Single().Message);
// …the run finishes after that flush.
recorder.RecordCompleted("Inst1", "Slow", 42);
var secondLog = new FakeSiteEventLogger();
Assert.True(await recorder.FlushAsync(secondLog));
var row = secondLog.OfType("script").Single();
Assert.Equal("0 runs: 1 completed, 0 failed, 0 timed out across 1 scripts", row.Message);
// The duration is carried too, so the completion is not merely counted.
using var doc = JsonDocument.Parse(row.Details!);
var script = doc.RootElement.GetProperty("scripts")[0];
Assert.Equal("Slow", script.GetProperty("scriptName").GetString());
Assert.Equal(0, script.GetProperty("started").GetInt64());
Assert.Equal(1, script.GetProperty("completed").GetInt64());
Assert.Equal(42, script.GetProperty("maxDurationMs").GetInt64());
}
[Fact]
public async Task CompletionOnlyEntry_DoesNotResurrectTheIdleFlushSuppression()
{
// The Completed>0 admission must not weaken "an idle interval emits nothing": a window
// in which literally nothing was recorded still has zero entries to admit.
var recorder = new ScriptRunSummaryRecorder();
recorder.RecordStarted("Inst1", "A");
recorder.RecordCompleted("Inst1", "A", 1);
Assert.True(await recorder.FlushAsync(new FakeSiteEventLogger()));
var idleLog = new FakeSiteEventLogger();
Assert.False(await recorder.FlushAsync(idleLog));
Assert.Empty(idleLog.Entries);
}
[Fact]
public async Task DurationTracking_ReportsAverageAndMax()
{