feat(site-runtime): script scheduler gauges — queue depth, busy threads, oldest-busy age (S2/UA5)
This commit is contained in:
+30
@@ -44,4 +44,34 @@ public class ScriptExecutionSchedulerTests
|
||||
var b = ScriptExecutionScheduler.Shared(options);
|
||||
Assert.Same(a, b);
|
||||
}
|
||||
|
||||
// SiteRuntime-S2/UA5: the scheduler exposes observability gauges so a stuck /
|
||||
// saturated script-execution pool is visible to operators via site health.
|
||||
[Fact]
|
||||
public async Task Gauges_ReflectBusyThreadAndQueueDepth()
|
||||
{
|
||||
using var scheduler = new ScriptExecutionScheduler(1);
|
||||
using var gate = new ManualResetEventSlim(false);
|
||||
|
||||
var blocking = Task.Factory.StartNew(() => gate.Wait(),
|
||||
CancellationToken.None, TaskCreationOptions.None, scheduler);
|
||||
var queued = Task.Factory.StartNew(() => { },
|
||||
CancellationToken.None, TaskCreationOptions.None, scheduler);
|
||||
|
||||
await WaitUntilAsync(() => scheduler.BusyThreadCount == 1);
|
||||
Assert.Equal(1, scheduler.QueueDepth); // second task waiting
|
||||
Assert.True(scheduler.OldestBusyAge > TimeSpan.Zero);
|
||||
|
||||
gate.Set();
|
||||
await Task.WhenAll(blocking, queued);
|
||||
await WaitUntilAsync(() => scheduler.BusyThreadCount == 0);
|
||||
Assert.Null(scheduler.OldestBusyAge);
|
||||
}
|
||||
|
||||
private static async Task WaitUntilAsync(Func<bool> condition)
|
||||
{
|
||||
for (var i = 0; i < 100 && !condition(); i++)
|
||||
await Task.Delay(50);
|
||||
Assert.True(condition(), "condition not met within timeout");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user