perf(site-runtime): ScriptActor trigger expressions evaluate on the script scheduler, coalesced, edge state actor-confined (P1)

This commit is contained in:
Joseph Doherty
2026-07-08 23:50:21 -04:00
parent 467edd74ac
commit 5aee90d155
2 changed files with 110 additions and 39 deletions
@@ -303,6 +303,43 @@ public class ScriptActorTests : TestKit, IDisposable
private Script<object?> CompileTriggerExpression(string expression) =>
_compilationService.CompileTriggerExpression("trigger-expr", expression).CompiledScript!;
/// <summary>
/// Compiles a trigger expression WITHOUT the trust validator so a test can use
/// <c>System.Threading.Thread</c> (forbidden in real scripts) to observe which
/// thread the evaluation runs on. Mirrors the real compile against
/// <see cref="TriggerExpressionGlobals"/>.
/// </summary>
private static Script<object?> CompileRawTriggerExpression(string expression)
{
var opts = ScriptOptions.Default
.WithReferences(typeof(object).Assembly, typeof(Enumerable).Assembly)
.WithImports("System", "System.Collections.Generic", "System.Linq", "System.Threading.Tasks");
var s = CSharpScript.Create<object?>(expression, opts, typeof(TriggerExpressionGlobals));
s.Compile();
return s;
}
[Fact]
public void ExpressionTrigger_EvaluatesOnScriptSchedulerThread_AndStillFires()
{
// The expression is TRUE only when evaluated on a script-execution thread.
// Before P1 it ran synchronously on the actor's dispatcher thread (name is
// NOT "script-execution-*") → false → no fire. After P1 it runs on the
// script scheduler → true → fire.
var expr = CompileRawTriggerExpression(
"System.Threading.Thread.CurrentThread.Name != null && " +
"System.Threading.Thread.CurrentThread.Name.StartsWith(\"script-execution-\")");
var (actor, instance) = CreateTriggeredActor(
"ExprThread",
"Expression",
"{\"expression\":\"true\",\"mode\":\"OnTrue\"}",
minTimeBetweenRuns: null,
expr);
actor.Tell(Change("Any", "1"));
instance.ExpectMsg<SetStaticAttributeCommand>(TimeSpan.FromSeconds(10)); // fired ⇒ evaluated off-dispatcher
}
[Fact]
public void ScriptActor_ConditionalWhileTrue_FiresOnEdgeThenReFiresWhileConditionHolds()
{