diff --git a/docs/plans/2026-06-16-ipsen-mes-movein-design.md b/docs/plans/2026-06-16-ipsen-mes-movein-design.md index 7784f562..7b52b5af 100644 --- a/docs/plans/2026-06-16-ipsen-mes-movein-design.md +++ b/docs/plans/2026-06-16-ipsen-mes-movein-design.md @@ -74,16 +74,26 @@ receiver is ready to accept a MoveIn. ## 4. Components ### A. ScadaBridge source change — inbound read-only DB helper -- New `InboundDatabaseHelper` backed by `IDatabaseGateway`, surface: - `T? QuerySingle(string conn, string sql, object? args = null)` and - `IReadOnlyList> Query(string conn, string sql, object? args = null)`. - **No write methods.** +- New `InboundDatabaseHelper` backed by `IDatabaseGateway`, surface (async — every call is + awaited and bound to the method deadline): + `Task QuerySingleAsync(string conn, string sql, object? args = null)`, + `Task>> QueryAsync(string conn, string sql, object? args = null)`, + and `Task ExecuteAsync(string conn, string sql, object? args = null)` (writes are supported — + see the correction below). - Add `Database` property to `InboundScriptContext`; construct it in `InboundScriptExecutor` from a service scope (gateway is scoped). Add the helper's assembly to the script `ScriptOptions.WithReferences(...)` and confirm `ForbiddenApiChecker` still passes (the script - references only `Database.QuerySingle`, never `System.Data`). + references only `Database.QuerySingleAsync`, never `System.Data`). - Unit tests with a fake `IDatabaseGateway`. +> **Correction (2026-06-25).** The shipped `InboundDatabaseHelper` is **async** — +> `QuerySingleAsync` / `QueryAsync` / `ExecuteAsync`, each `await`ed — not the synchronous +> `QuerySingle`/`Query` sketched in the original draft above, and **writes are supported** +> (InboundAPI-026) rather than read-only. Scripts MUST call `await Database.QuerySingleAsync(...)`. +> Three deployed methods (`IpsenMESMoveIn`, `MesMoveIn`, `MesMoveOut`) were authored from the old +> `Database.QuerySingle` spelling and failed Roslyn compilation in production until corrected +> (2026-06-25). The authoritative surface lives in `docs/requirements/Component-InboundAPI.md`. + ### B. Rewrite inbound `/api/IpsenMESMoveIn` script (data, via management API) Pseudocode (always returns the 3-field shape; never throws out): ```csharp @@ -96,7 +106,7 @@ try { var side = suf == "A" ? "Left" : suf == "B" ? "Right" : null; if (side == null) return new { WasSuccessful = false, ErrorText = $"Unsupported side '{suf}'", BatchID = 0 }; - var code = Database.QuerySingle("BTDB", + var code = await Database.QuerySingleAsync("BTDB", "SELECT TOP 1 Code FROM dbo.Machine WHERE SAPID=@s", new { s = sap }); if (string.IsNullOrEmpty(code)) return new { WasSuccessful = false, ErrorText = $"No machine for SAP {sap}", BatchID = 0 };