diff --git a/Component-ExternalSystemGateway.md b/Component-ExternalSystemGateway.md index bb91f7f..534bf1b 100644 --- a/Component-ExternalSystemGateway.md +++ b/Component-ExternalSystemGateway.md @@ -73,12 +73,29 @@ All external system calls are **HTTP/REST** with **JSON** serialization: - Response bodies are deserialized from JSON into the method's defined return type. - Credentials (API key header or Basic Auth header) are attached to every request per the system's authentication configuration. +## External System Call Modes + +Scripts choose between two call modes per invocation, mirroring the dual-mode database access pattern: + +### Synchronous (Real-time) +- Script calls `ExternalSystem.Call("systemName", "methodName", params)`. +- The HTTP request is executed immediately. The script blocks until the response is received or the timeout elapses. +- **All failures** (transient and permanent) return an error to the calling script. No store-and-forward buffering. +- Use for request/response interactions where the script needs the result (e.g., fetching a recipe, querying inventory). + +### Cached (Store-and-Forward) +- Script calls `ExternalSystem.CachedCall("systemName", "methodName", params)`. +- The call is attempted immediately. If it succeeds, the response is discarded (fire-and-forget). +- On **transient failure** (connection refused, timeout, HTTP 5xx), the call is routed to the Store-and-Forward Engine for retry per the system's retry settings. The script does **not** block — the call is buffered and the script continues. +- On **permanent failure** (HTTP 4xx), the error is returned **synchronously** to the calling script. No retry — the request itself is wrong. +- Use for outbound data pushes where deferred delivery is acceptable (e.g., posting production data, sending quality reports). + ## Call Timeout & Error Handling - Each external system definition specifies a **timeout** that applies to all method calls on that system. -- Error classification determines whether the Store-and-Forward Engine retries the call: - - **Transient failures** (connection refused, timeout, HTTP 5xx): The call is routed to the Store-and-Forward Engine for retry per the system's retry settings. The script does **not** block waiting for eventual delivery — the call is buffered and the script continues. - - **Permanent failures** (HTTP 4xx): No retry. The error is returned **synchronously** to the calling script for handling (log, notify, try different parameters, etc.). The failure is logged to Site Event Logging. +- Error classification by HTTP response: + - **Transient failures** (connection refused, timeout, HTTP 5xx): Behavior depends on call mode — `CachedCall` buffers for retry; `Call` returns error to script. + - **Permanent failures** (HTTP 4xx): Always returned to the calling script regardless of call mode. Logged to Site Event Logging. - This classification ensures the S&F buffer is not polluted with requests that will never succeed. ## Database Connection Management diff --git a/Component-SiteRuntime.md b/Component-SiteRuntime.md index 6d1efdc..db23704 100644 --- a/Component-SiteRuntime.md +++ b/Component-SiteRuntime.md @@ -205,7 +205,8 @@ Available to all Script Execution Actors and Alarm Execution Actors: - `Scripts.CallShared("scriptName", parameters)` — Execute shared script code inline (direct method invocation). The call includes the current recursion depth. ### External Systems -- Access to predefined external system API methods (see External System Gateway component). +- `ExternalSystem.Call("systemName", "methodName", params)` — Synchronous HTTP call. Blocks until response or timeout. All failures return to script. Use when the script needs the result. +- `ExternalSystem.CachedCall("systemName", "methodName", params)` — Fire-and-forget with store-and-forward on transient failure. Use for outbound data pushes where deferred delivery is acceptable. ### Notifications - `Notify.To("listName").Send("subject", "message")` — Send an email notification via a named notification list. diff --git a/HighLevelReqs.md b/HighLevelReqs.md index f93e2bd..8e4c1d9 100644 --- a/HighLevelReqs.md +++ b/HighLevelReqs.md @@ -221,7 +221,7 @@ Scripts executing on a site for a given instance can: - **Write** attribute values on that instance. For attributes with a data source reference, the write goes to the Data Connection Layer which writes to the physical device; the in-memory value updates when the device confirms the new value via the existing subscription. For static attributes, the write updates the in-memory value directly. - **Call other scripts** on that instance via `Instance.CallScript("scriptName", params)`. Calls use the Akka ask pattern and return the called script's return value. Script-to-script calls support concurrent execution. - **Call shared scripts** via `Scripts.CallShared("scriptName", params)`. Shared scripts execute **inline** in the calling Script Actor's context — they are compiled code libraries, not separate actors. -- **Call external system API methods** (see Section 5). +- **Call external system API methods** in two modes: `ExternalSystem.Call()` for synchronous request/response, or `ExternalSystem.CachedCall()` for fire-and-forget with store-and-forward on transient failure (see Section 5). - **Send notifications** (see Section 6). - **Access databases** by requesting an MS SQL client connection by name (see Section 5.5). diff --git a/docs/plans/2026-03-16-external-system-gateway-refinement-design.md b/docs/plans/2026-03-16-external-system-gateway-refinement-design.md index ab9981b..8275e26 100644 --- a/docs/plans/2026-03-16-external-system-gateway-refinement-design.md +++ b/docs/plans/2026-03-16-external-system-gateway-refinement-design.md @@ -24,13 +24,15 @@ The External System Gateway doc lacked specification for the invocation protocol - **Per-system timeout** — one timeout value applies to all methods on a given external system. - Defined in the external system definition. -### Error Classification -- **Transient failures** (connection errors, timeouts, HTTP 5xx): Routed to Store-and-Forward for retry. Script does not block. -- **Permanent failures** (HTTP 4xx): No retry. Error returned synchronously to the calling script. Logged to Site Event Logging. -- S&F buffer only accepts transient failures to avoid accumulating unrecoverable requests. +### Dual Call Modes +- **`ExternalSystem.Call()`**: Synchronous request/response. All failures (transient and permanent) return to the script. No S&F buffering. Use when the script needs the result. +- **`ExternalSystem.CachedCall()`**: Fire-and-forget with S&F on transient failure. Use for outbound data pushes where deferred delivery is acceptable. +- Mirrors the existing `Database.Connection()` / `Database.CachedWrite()` pattern. -### Permanent Failure Behavior -- Synchronous error back to script, consistent with DCL write failure handling. +### Error Classification +- **Transient failures** (connection errors, timeouts, HTTP 5xx): `CachedCall` buffers for retry; `Call` returns error to script. +- **Permanent failures** (HTTP 4xx): Always returned to the calling script regardless of call mode. Logged to Site Event Logging. +- S&F buffer only accepts transient failures to avoid accumulating unrecoverable requests. ### Database Connection Pooling - Standard ADO.NET connection pooling per named connection. No custom pool logic. @@ -43,8 +45,10 @@ The External System Gateway doc lacked specification for the invocation protocol | Document | Change | |----------|--------| -| `Component-ExternalSystemGateway.md` | Updated External System Definition fields (base URL, auth modes, timeout, HTTP method/path per method). Added 3 new sections: Invocation Protocol, Call Timeout & Error Handling, Database Connection Management. | +| `Component-ExternalSystemGateway.md` | Updated External System Definition fields. Added sections: External System Call Modes (dual-mode API), Invocation Protocol, Call Timeout & Error Handling, Database Connection Management. | | `Component-StoreAndForward.md` | Clarified that only transient failures are buffered; 4xx errors are not queued. | +| `Component-SiteRuntime.md` | Updated Script Runtime API with `ExternalSystem.Call()` and `ExternalSystem.CachedCall()`. | +| `HighLevelReqs.md` | Updated script capabilities (Section 4.4) to reflect dual call modes. | ## Alternatives Considered @@ -54,3 +58,4 @@ The External System Gateway doc lacked specification for the invocation protocol - **All failures retryable**: Rejected — retrying 4xx errors pollutes the S&F buffer with requests that will never succeed. - **Custom connection pooling**: Rejected — ADO.NET pooling is battle-tested and handles this scenario natively. - **XML serialization option**: Rejected — JSON-only is consistent with REST-only; XML systems can use a wrapper. +- **Per-method sync/cached flag**: Rejected — the same method may need synchronous calls in one script and cached in another. Script author chooses per invocation.