fix(management): single-flight large /management bodies at the HTTP edge (409 IMPORT_IN_PROGRESS) and parse the command off the request stream (review 2026-10-21 05/M2)

This commit is contained in:
Joseph Doherty
2026-10-22 09:22:22 -04:00
parent 72f96bdbcb
commit b0c863c6a1
3 changed files with 335 additions and 38 deletions
@@ -67,6 +67,9 @@ Content-Type: application/json
- `ManagementUnauthorized` → HTTP 403 with `{ "error": "...", "code": "UNAUTHORIZED" }`
- Authentication failure → HTTP 401
- Actor timeout → HTTP 504
- Large request while another is in flight → HTTP 409 with `{ "error": "...", "code": "IMPORT_IN_PROGRESS" }` (see below)
**Large-request single-flight and streaming parse (review 2026-10-21 05/M2).** The body cap is raised to 200 MB for bundle import/preview. A request whose `Content-Length` exceeds 16 MB — or is unknown (chunked) — must take a per-node `LargeRequestGate` with `Wait(0)` *after authentication and before the body is read*, and holds it until the actor replies; a second large request is refused with **409 `IMPORT_IN_PROGRESS`** (retry when the first completes) rather than materialising another copy and then waiting at the actor's `TransportGate`. Ordinary (small) commands never touch the gate. The command is parsed straight off the request stream (`ParseCommandAsync`: one UTF-8 buffer, the payload deserialised directly into the command type once `command` has been read — the CLI sends `command` first; a payload that precedes it is buffered as a `JsonElement`), replacing the old `ReadToEnd` string → `JsonDocument` → `GetRawText` → `Deserialize` chain (~4 copies, ~1.1 GB peak for a 200 MB body). Error messages (`Invalid JSON body.`, `Missing 'command' field.`, `Unknown command: '…'.`, `Failed to deserialize payload: …`) are unchanged.
The endpoint performs LDAP authentication and role resolution server-side, collapsing the CLI's previous two-step flow (ResolveRoles + actual command) into a single HTTP round-trip.