M54: harden operations and demo resilience
This commit is contained in:
@@ -11,6 +11,7 @@ from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
from app.core.config import get_settings
|
||||
from app.main import app
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
@@ -106,6 +107,58 @@ def check_workflows(failures: list[str]) -> None:
|
||||
serialized = raw.decode("utf-8")
|
||||
if "http://fleetops.itworx.tech" in serialized:
|
||||
fail(f"{filename} contains a cleartext Fleet Ops callback", failures)
|
||||
if filename == "fleet-ops-vehicle-return.json":
|
||||
check_return_workflow_timing(definition, failures)
|
||||
|
||||
|
||||
def check_return_workflow_timing(definition: dict, failures: list[str]) -> None:
|
||||
"""Keep nested retry budgets inside the dispatcher's recoverable delivery lease."""
|
||||
nodes_by_name = {node.get("name"): node for node in definition.get("nodes", [])}
|
||||
validation_code = (
|
||||
nodes_by_name.get("Validate and derive follow-up", {}).get("parameters", {}).get("jsCode", "")
|
||||
)
|
||||
if not all(field in validation_code for field in ("event_id", "correlation_id")):
|
||||
fail(
|
||||
"Vehicle-return workflow must preserve event_id and correlation_id for its callback",
|
||||
failures,
|
||||
)
|
||||
required_nodes = ("Record follow-up", "Report workflow heartbeat")
|
||||
workflow_budget_ms = 0
|
||||
for name in required_nodes:
|
||||
node = nodes_by_name.get(name)
|
||||
if not isinstance(node, dict):
|
||||
fail(f"Vehicle-return workflow is missing timing-critical node {name!r}", failures)
|
||||
return
|
||||
options = node.get("parameters", {}).get("options", {})
|
||||
timeout_ms = options.get("timeout")
|
||||
if node.get("retryOnFail") is not True:
|
||||
fail(f"{name!r} must retain bounded retries", failures)
|
||||
return
|
||||
max_tries = node.get("maxTries")
|
||||
wait_ms = node.get("waitBetweenTries", 0)
|
||||
if not all(
|
||||
isinstance(value, int) and not isinstance(value, bool) and value > 0
|
||||
for value in (timeout_ms, max_tries)
|
||||
) or (
|
||||
max_tries < 2
|
||||
or not isinstance(wait_ms, int)
|
||||
or isinstance(wait_ms, bool)
|
||||
or wait_ms < 0
|
||||
):
|
||||
fail(f"{name!r} has an invalid timeout/retry budget", failures)
|
||||
return
|
||||
workflow_budget_ms += timeout_ms * max_tries + wait_ms * (max_tries - 1)
|
||||
|
||||
settings = get_settings()
|
||||
dispatcher_timeout_ms = settings.n8n_http_timeout_seconds * 1000
|
||||
lease_ms = settings.n8n_delivery_lease_seconds * 1000
|
||||
if not workflow_budget_ms < dispatcher_timeout_ms < lease_ms:
|
||||
fail(
|
||||
"Vehicle-return timing contract violated: complete callback/heartbeat retry "
|
||||
f"budget {workflow_budget_ms}ms must be below dispatcher timeout "
|
||||
f"{dispatcher_timeout_ms:g}ms, which must be below delivery lease {lease_ms:g}ms",
|
||||
failures,
|
||||
)
|
||||
|
||||
|
||||
def main() -> int:
|
||||
|
||||
@@ -12,6 +12,7 @@ LINE_LIMITS = {
|
||||
}
|
||||
BYTE_LIMITS = {
|
||||
"frontend/src/styles.css": 78_000,
|
||||
"frontend/src/styles-architecture-flow.css": 9_000,
|
||||
"frontend/src/styles-data-quality.css": 8_000,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user