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:
@@ -307,6 +307,38 @@ public class FlowDebugRunnerTests
|
||||
Assert.Contains(_central, e => e.AsRow().Kind == AuditKind.RouteCall);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gitea #54: on the method entry the routed reply reaches the runner through RouteHelper's
|
||||
/// sink, so the site collector's truncation flags must ride that path too.
|
||||
/// </summary>
|
||||
/// <param name="truncated">The site's step-row truncation flag.</param>
|
||||
/// <param name="logsTruncated">The site's log-row truncation flag.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Theory]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public async Task RunMethod_OrsTheRoutedSitesTruncationFlagsIntoTheResult(bool truncated, bool logsTruncated)
|
||||
{
|
||||
var method = new ApiMethod("M", "x") { Id = 7, TimeoutSeconds = 5 };
|
||||
_apiRepo.GetApiMethodByIdAsync(7, Arg.Any<CancellationToken>()).Returns(method);
|
||||
_locator.GetSiteIdForInstanceAsync("inst", Arg.Any<CancellationToken>()).Returns("site-a");
|
||||
var child = Guid.NewGuid();
|
||||
var siteRun = ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptRun, AuditStatus.Delivered,
|
||||
executionId: child, target: "work");
|
||||
_router.RouteToCallAsync("site-a", Arg.Any<RouteToCallRequest>(), Arg.Any<CancellationToken>())
|
||||
.Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, 7, null,
|
||||
DateTimeOffset.UtcNow, child, [siteRun], truncated, logsTruncated));
|
||||
_executor.RegisterHandler("M", ctx => ctx.Route.To("inst").Call("work"));
|
||||
|
||||
var result = await Runner().RunMethodAsync(_services.BuildServiceProvider(),
|
||||
new FlowDebugRunMethodCommand(7, null), Deployer, CancellationToken.None);
|
||||
|
||||
Assert.True(result.Completed, result.Error);
|
||||
Assert.Equal(truncated, result.Truncated);
|
||||
Assert.Equal(logsTruncated, result.LogsTruncated);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a site clock behind central still returns the sink events in emission order.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
@@ -908,6 +940,35 @@ public class FlowDebugRunnerTests
|
||||
Assert.Equal("OtherScript", result.Events[1].Target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gitea #54: a call-kind script run whose SITE collector dropped rows reports truncation on
|
||||
/// the result, even though central's own collector saw only the (short) list the site sent.
|
||||
/// </summary>
|
||||
/// <param name="truncated">The site's step-row truncation flag.</param>
|
||||
/// <param name="logsTruncated">The site's log-row truncation flag.</param>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Theory]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public async Task RunScript_CallKind_OrsTheSitesTruncationFlagsIntoTheResult(bool truncated, bool logsTruncated)
|
||||
{
|
||||
WireScript(CallScript("Manual", """{"type":"object","properties":{"n":{"type":"integer"}},"required":["n"]}""", timeout: 5));
|
||||
var child = Guid.NewGuid();
|
||||
var siteRun = ScadaBridgeAuditEventFactory.Create(AuditChannel.ScriptTrace, AuditKind.ScriptRun, AuditStatus.Delivered,
|
||||
executionId: child, target: "Manual");
|
||||
_router.RouteToCallAsync("site-a", Arg.Any<RouteToCallRequest>(), Arg.Any<CancellationToken>())
|
||||
.Returns(ci => new RouteToCallResponse(((RouteToCallRequest)ci[1]).CorrelationId, true, 42, null,
|
||||
DateTimeOffset.UtcNow, child, [siteRun], truncated, logsTruncated));
|
||||
|
||||
var result = await Runner().RunScriptAsync(_services.BuildServiceProvider(),
|
||||
new FlowDebugRunScriptCommand(5, "Manual", Json("{\"n\":3}"), null), Deployer, CancellationToken.None);
|
||||
|
||||
Assert.True(result.Completed, result.Error);
|
||||
Assert.Equal(truncated, result.Truncated);
|
||||
Assert.Equal(logsTruncated, result.LogsTruncated);
|
||||
}
|
||||
|
||||
/// <summary>Verifies that a call-kind script run routes a traced call and returns the root route-call row followed by the site rows.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user