fix(central-ui,cli): Flow Debugger client waits derive from the method timeout / wait window instead of a fixed 2 minutes (arch-review F4)
Claude-Session: https://claude.ai/code/session_01NcMG6xXdsJbmD2wYAgkK29
This commit is contained in:
@@ -14,8 +14,12 @@ namespace ZB.MOM.WW.ScadaBridge.CLI.Commands;
|
||||
/// </summary>
|
||||
public static class FlowDebugCommands
|
||||
{
|
||||
/// <summary>Client-side wait for the run commands — must exceed the server's run grace + trigger window.</summary>
|
||||
internal static readonly TimeSpan RunTimeout = TimeSpan.FromMinutes(2);
|
||||
/// <summary>
|
||||
/// Slack the CLI's HTTP wait adds over the server's own bound (arch-review F4): the CLI
|
||||
/// process is one more hop out from the management Ask than the Central UI's in-process
|
||||
/// call, so it carries a larger fixed margin than <c>FlowDebugService.ClientSlack</c> (15s).
|
||||
/// </summary>
|
||||
private const int ClientSlackSeconds = 25;
|
||||
|
||||
/// <summary>Builds the <c>flow-debug</c> command with its subcommands using the given shared CLI options.</summary>
|
||||
/// <param name="urlOption">Shared management URL option.</param>
|
||||
@@ -38,11 +42,24 @@ public static class FlowDebugCommands
|
||||
{
|
||||
var methodIdOption = new Option<int>("--method-id") { Description = "Inbound API method ID", Required = true };
|
||||
var paramsOption = new Option<string?>("--params") { Description = "Flat JSON object of method parameters (validated against the method's schema)" };
|
||||
var timeoutOption = new Option<int>("--timeout-seconds")
|
||||
{
|
||||
Description = "Client-side wait for the run; set to the method's TimeoutSeconds + 25 for long methods",
|
||||
DefaultValueFactory = _ => 120,
|
||||
};
|
||||
var cmd = new Command("run-method") { Description = "Run an inbound API method on the active central node with full tracing and print the flow's steps" };
|
||||
cmd.Add(methodIdOption);
|
||||
cmd.Add(paramsOption);
|
||||
cmd.Add(timeoutOption);
|
||||
cmd.SetAction(async (ParseResult result) =>
|
||||
{
|
||||
var timeoutSeconds = result.GetValue(timeoutOption);
|
||||
if (timeoutSeconds <= 0)
|
||||
{
|
||||
OutputFormatter.WriteError("--timeout-seconds must be greater than zero.", "INVALID_ARGUMENT");
|
||||
return 1;
|
||||
}
|
||||
|
||||
JsonElement? parameters;
|
||||
try
|
||||
{
|
||||
@@ -57,7 +74,7 @@ public static class FlowDebugCommands
|
||||
return await CommandHelpers.ExecuteCommandAsync(
|
||||
result, urlOption, formatOption, usernameOption, passwordOption,
|
||||
new FlowDebugRunMethodCommand(result.GetValue(methodIdOption), parameters),
|
||||
timeout: RunTimeout,
|
||||
timeout: TimeSpan.FromSeconds(timeoutSeconds),
|
||||
tableProjector: FlowDebugTableProjection.ProjectEvents);
|
||||
});
|
||||
return cmd;
|
||||
@@ -90,7 +107,7 @@ public static class FlowDebugCommands
|
||||
result.GetValue(attributeOption)!,
|
||||
result.GetValue(valueOption)!,
|
||||
waitSeconds),
|
||||
timeout: RunTimeout,
|
||||
timeout: TimeSpan.FromSeconds(waitSeconds + ClientSlackSeconds),
|
||||
tableProjector: FlowDebugTableProjection.ProjectEvents);
|
||||
});
|
||||
return cmd;
|
||||
|
||||
@@ -2305,16 +2305,17 @@ Run an inbound API method with the given parameters, exactly as an external call
|
||||
and print the traced flow.
|
||||
|
||||
```sh
|
||||
scadabridge --url <url> flow-debug run-method --method-id <int> [--params <json>]
|
||||
scadabridge --url <url> flow-debug run-method --method-id <int> [--params <json>] [--timeout-seconds 120]
|
||||
```
|
||||
|
||||
| Option | Required | Description |
|
||||
|--------|----------|-------------|
|
||||
| `--method-id` | yes | Inbound API method ID (`api-method list`) |
|
||||
| `--params` | no | Flat JSON object of parameters, validated against the method's parameter schema. Omit for a parameterless method. |
|
||||
| `--timeout-seconds` | no | Client-side wait for the run (default 120). Raise this above the method's own `TimeoutSeconds + 25` for a long-running method, or the client gives up before the server's own run grace does. |
|
||||
|
||||
The client waits up to 2 minutes. Parameters that fail schema validation are reported as
|
||||
`VALIDATION_FAILED` without running the script.
|
||||
Parameters that fail schema validation are reported as `VALIDATION_FAILED` without running
|
||||
the script.
|
||||
|
||||
#### `flow-debug run-value-change`
|
||||
|
||||
@@ -2332,7 +2333,8 @@ scadabridge --url <url> flow-debug run-value-change --instance-id <int> --attrib
|
||||
| `--value` | yes | Value to write, in canonical string form |
|
||||
| `--wait-seconds` | no | How long to wait for a triggered run before reporting `NO_TRIGGER_WITHIN_WINDOW` (default 45) |
|
||||
|
||||
The write itself is real — the attribute changes — and is the root step of the flow.
|
||||
The client waits `--wait-seconds` + 25 (no separate option — the client's HTTP wait always
|
||||
derives from `--wait-seconds`). The write itself is real — the attribute changes — and is the root step of the flow.
|
||||
A static attribute triggers directly; a data-sourced attribute triggers when the device
|
||||
echoes the write back, which the site's trace arm (`SiteRuntime:TraceArmWindowSeconds`,
|
||||
default 30) correlates back to this run.
|
||||
|
||||
Reference in New Issue
Block a user