feat(flow-debugger): carry site-side trace truncation on the route reply (ScadaBridge#54)

ScriptCallResult and RouteToCallResponse gain trailing Truncated/LogsTruncated,
filled from the site FlowTraceCollector after Complete(); RouteToCallResponseDto
fields 8/9 carry them (sitecommand regen). FlowDebugRunner ORs them into
FlowDebugRunResult on the script entry, and on the method entry through a new
optional truncation sink on RouteHelper.WithTraceSink (carried through every
With* clone). Previously a site run whose collector dropped rows came back as a
silently short list. Older sites send false.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
This commit is contained in:
Joseph Doherty
2026-11-09 12:37:57 -05:00
parent 5310fd0e26
commit 6d5bb6189f
15 changed files with 484 additions and 155 deletions
@@ -3357,7 +3357,10 @@ public class DeploymentManagerActor : ReceiveActor, IWithTimers
// Flow Debugger (design §5.4): the site run's id and, for a traced
// run, its ScriptTrace events — returned inline so a Live run is
// instant. Null from an untraced run.
result.ExecutionId, result.TraceEvents);
result.ExecutionId, result.TraceEvents,
// Gitea #54: the site collector's truncation flags ride along so a
// short inline list is labelled short on the Flow Debugger page.
result.Truncated, result.LogsTruncated);
}
return new RouteToCallResponse(
request.CorrelationId, false, null,
@@ -452,9 +452,8 @@ internal static class ScriptRunLauncher
// Send result to requester if this was an Ask-based call
if (!replyTo.IsNobody())
{
replyTo.Tell(new ScriptCallResult(
correlationId, true, state.ReturnValue, null,
context.ExecutionId, collector?.Complete()));
replyTo.Tell(BuildCallResult(
correlationId, true, state.ReturnValue, null, context.ExecutionId, collector));
}
// Operational `script` event — execution completed successfully. Same gating as
@@ -493,8 +492,8 @@ internal static class ScriptRunLauncher
if (!replyTo.IsNobody())
{
replyTo.Tell(new ScriptCallResult(
correlationId, false, null, errorMsg, context?.ExecutionId, collector?.Complete()));
replyTo.Tell(BuildCallResult(
correlationId, false, null, errorMsg, context?.ExecutionId, collector));
}
completionTarget.Tell(new ScriptActor.ScriptExecutionCompleted(scriptName, false, errorMsg));
@@ -523,8 +522,8 @@ internal static class ScriptRunLauncher
if (!replyTo.IsNobody())
{
replyTo.Tell(new ScriptCallResult(
correlationId, false, null, errorMsg, context?.ExecutionId, collector?.Complete()));
replyTo.Tell(BuildCallResult(
correlationId, false, null, errorMsg, context?.ExecutionId, collector));
}
completionTarget.Tell(new ScriptActor.ScriptExecutionCompleted(scriptName, false, errorMsg));
@@ -540,6 +539,22 @@ internal static class ScriptRunLauncher
}
}
/// <summary>
/// Builds the Ask reply for a run. Closes the inline collector FIRST, then reads its
/// truncation flags, so a site run whose collector dropped rows tells the caller its
/// <c>TraceEvents</c> list is short instead of returning a silently short list (Gitea #54).
/// </summary>
private static ScriptCallResult BuildCallResult(
string correlationId, bool success, object? returnValue, string? error,
Guid? executionId, FlowTraceCollector? collector)
{
var traceEvents = collector?.Complete();
return new ScriptCallResult(
correlationId, success, returnValue, error, executionId, traceEvents,
Truncated: collector?.Truncated ?? false,
LogsTruncated: collector?.LogsTruncated ?? false);
}
/// <summary>
/// Arch-review F7: a traced run that never launched (shed at the in-flight cap, or
/// suppressed by <c>MinTimeBetweenRuns</c>) still leaves a <c>Failed</c>