using Akka.Actor;
using Akka.TestKit.Xunit2;
using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting;
using Microsoft.Extensions.Logging.Abstractions;
using ZB.MOM.WW.ScadaBridge.Commons.Messages.ScriptExecution;
using ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening;
using ZB.MOM.WW.ScadaBridge.HealthMonitoring;
using ZB.MOM.WW.ScadaBridge.SiteRuntime.Actors;
using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
using ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.TestSupport;
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Actors;
///
/// WP3.1 test group 4 — the stuck-script watchdog now REPLACES the thread a wedged script is
/// holding, not just names it.
///
/// Before WP3.1 the watchdog was observability only: a script blocked in synchronous,
/// uninterruptible I/O never observes the cooperative cancellation the timeout requests, so
/// the pool simply lost that dedicated thread — permanently, and silently apart from one log
/// line. Eight such scripts left the site with no script execution at all. The watchdog now
/// detaches the worker (it exits when its body finally returns) and starts a replacement, and
/// the count of live detached workers is surfaced on the site health report as
/// DetachedScriptThreads. Replacement is capped at the pool size, because bounded
/// starvation beats unbounded thread growth when scripts wedge en masse.
///
public class StuckScriptWatchdogTests : TestKit, IDisposable
{
private readonly SharedScriptLibrary _sharedLibrary;
public StuckScriptWatchdogTests()
{
var compilationService = new ScriptCompilationService(
NullLogger.Instance);
_sharedLibrary = new SharedScriptLibrary(
compilationService, NullLogger.Instance);
WatchdogHooks.Gate = new SemaphoreSlim(0);
}
void IDisposable.Dispose()
{
// Free any still-wedged worker before tearing down, so no test leaves a blocked thread.
WatchdogHooks.Gate.Release(8);
Shutdown();
}
private static Script