Skip to content

Bound external payload HTTP memory and align SAPI limits - #142

Merged
rmcdaniel merged 6 commits into
mainfrom
fix/stream-external-payload-transport
Sep 8, 2026
Merged

Bound external payload HTTP memory and align SAPI limits#142
rmcdaniel merged 6 commits into
mainfrom
fix/stream-external-payload-transport

Conversation

@rmcdaniel

@rmcdaniel rmcdaniel commented Sep 8, 2026

Copy link
Copy Markdown
Member

Problem

Refs #141. Server 2.3.1's Apache image rejects its advertised 64 MiB external payload size before Laravel; raising only the SAPI limit then exhausts memory.

Implementation

  • Stream uploads and verified downloads; preserve namespace authorization, quotas, integrity, retention and retry cleanup.
  • Enforce ordinary body limits before normalization; disable eager SAPI form parsing and keep PHP warnings out of API bodies.
  • Retain large workflow/activity inputs and results as verified references. Validate command/result Avro through official schema traversal without materializing collections or the full base64 body.
  • Explicitly omit oversized decoded previews while retaining authenticated access to full payloads.
  • Use published Workflow 2.0.7 metadata projections (workflow#491/#492).
  • Package as Server 2.3.2 / Helm 0.1.81. Generated release identity only; no schema or protocol version change.

Verification

Built actual production Dockerfile image from Server 268681d with published Workflow 2.0.7, no source overlays:

  • Image ID sha256:2635ab268aee814522d19b57516cc4fac6900514b554002c0fecbd97f0e85a1d.
  • Real Apache HTTP: concurrent exact 64 MiB uploads and fetch integrity; over-limit fixed/chunked requests; ordinary JSON/form POST/PUT/PATCH rejection; retained workflow input/description; concurrent exact-limit workflow completions; standalone activity input/poll/completion/result all pass.
  • A fresh Composer install of published PHP SDK 2.0.7 reads both full workflow results and verifies decoded byte identity.
  • Cold Server/MySQL restart: completed workflow/activity state, reference SHA-256, official Avro decode and a second fresh SDK consumer all pass.
  • PHP heap 128 MiB; HTTP container 176 MiB / 1 CPU; MySQL 400 MiB / 1 CPU. Zero OOM/OOM kills. Memory pressure did cause 6,004 reclaim max events; this does not demonstrate spare concurrency headroom. Client/decoder runs separately.
  • Temporary streams used disk, not tmpfs. Validation needs temporary decoded storage in addition to the encoded snapshot, and UTF-8 validation may hold one complete text scalar. Concurrency and temporary-storage capacity must be sized explicitly.

Hosted checks at 268681d: 2,140 tests / 42,990 assertions, 6 PHPUnit deprecations; MySQL replay/query HTTP and performance pass. Focused validation/transport/envelope/activity checks: 117 tests / 840 assertions pass. Broad local Unit failures were reproduced on the unchanged target; that suite is not claimed green.

Corpus blocker resolved through public guidance .github#125 and explicit boundary review. Transport/memory fixes do not manufacture wire fixtures; existing fixtures still execute and actual wire defects still require new fixtures/proofs. All 71 policy tests pass.

55c15cd changes only generated release identity (25 files). Source-release tests 3/3 and metadata/diff checks pass; hosted checks are rerunning on that exact candidate.

Release Acceptance

Merge after required checks. Publish the immutable patch image and chart through the repository release workflow, then verify native HTTP/SDK/cold behavior using the published image before closing #141. Production remains unchanged; this PR does not qualify a particular Cloud storage topology.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Progress in 14bdc992: retained workflow inputs no longer download and re-upload their stored bytes, and workflow/command description previews no longer decode external objects above the ordinary API limit. Full opaque envelopes remain available; omission is explicit. Query and message-stream resolution keep their existing semantics.

Local checks: 2,055 Feature tests / 41,593 assertions, zero failures (6 PHPUnit deprecations, 3 configured skips); targeted transport/stream tests pass. Pint and diff checks pass. The broader Unit suite is not green: 60 failures and 2 errors, including obsolete conformance/source assertions and missing fixture prerequisites. I am comparing the target revision before attributing them; this is not an all-tests-pass claim. The existing codec-corpus gate also remains unresolved.

Native Apache qualification uses published Server 2.3.1 plus the candidate source/INI, MySQL 8.0.46, PHP 8.3, PHP memory limit 128 MiB, HTTP container 176 MiB/1 CPU. In the fresh run: two concurrent exact 64 MiB uploads, two full hash-verified fetches, 64 MiB+1 rejection, POST/PUT/PATCH ordinary JSON/form rejection, chunked request rejection, retained workflow start and bounded description all pass. Cgroup OOM/OOM-kill counters stayed zero. Published PHP SDK 2.0.7 completed the large-input workflow and read its 50,331,630-byte input digest back correctly.

Still not release-ready: explicitly completing with a previously uploaded 64 MiB external result exhausts PHP memory in Avro validation. A normal PHP SDK return value of this size is sent inline and gets 413; that separate outbound capability gap is tracked in sdk-php #63. These are not covered by the successful large-input run. Keep #141 open and this PR draft; no production deployment or advertised-capacity change.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Hosted update: the Feature job completed 2,136 tests / 42,949 assertions with zero test failures (6 PHPUnit deprecations), including its configured backend fixtures. Its red conclusion is the subsequent codec-corpus growth check, not PHPUnit. MySQL replay/query HTTP and both performance checks also passed. The corpus requirement and the confirmed large-result validation defect remain outstanding; no merge or release is authorized by these partial passes.

@rmcdaniel

rmcdaniel commented Sep 8, 2026

Copy link
Copy Markdown
Member Author

Unchanged target d9bed707 also fails the broad Unit suite (1,596 tests, 70 failures, 2 errors). Focused target-revision reruns reproduce the obsolete legacy-codec expectation, outdated LongPoller override signature, and conformance scenario-count assertion. The candidate had 1,599 tests, 60 failures, 2 errors in this local environment; this does not replace the passing hosted Feature checks or justify ignoring the outstanding corpus gate.

Cold recovery is verified: after restarting both Apache Server and MySQL, a fresh published SDK client again read the previously completed 64 MiB-input workflow and matched its result digest. The deliberately failed large-output request did not corrupt that prior result. All native runtime/SDK containers, their network and database volume have now been removed. No production changes.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Published dependency follow-through: 832b490 pins Workflow 2.0.7 from Packagist. The package/platform check and all 16 published Laravel/PHP upgrade cells pass (https://github.com/durable-workflow/workflow/actions/runs/34206995339); its src/ tree exactly matches the earlier native-HTTP-qualified candidate. All 117 focused Server tests / 840 assertions also pass with the downloaded package, no source overlay.

Hosted qualification is rerunning at 832b490. The previous seven standalone-activity failures were the deliberately unupdated 2.0.6 dependency (unknown decodePayloads parameter), not a newly discovered product defect; that dependency is now corrected. The separate codec-corpus growth/proof check remains unresolved and this PR remains draft. No Server release or production deployment has occurred.

@rmcdaniel

Copy link
Copy Markdown
Member Author

Transport review completed against d9bed70 (published 2.3.1 baseline), following the now-merged evidence guidance in durable-workflow/.github#125:

  • RuntimeExternalPayloadController, upload-body handling, registry and streaming drivers change byte transport and snapshot ownership, not the Avro wire representation. Existing namespace/role/quota/integrity tests still pass; wrong hashes, truncated backing writes, oversized objects and unclaimed-expiry behavior are covered.
  • WorkflowStartService and AvroPayloadEnvelopeResolver retain the same already-verified external object instead of fetching/re-uploading it. Metadata/result controllers preserve the opaque envelope; oversized decoded previews are explicitly omitted. Small decoded values retain their existing behavior.
  • WorkerController and ActivityTaskController retain validated references for completion and activity scheduling. Avro validation still checks the official single-object fingerprint, strict scalar/UTF-8 rules, collection blocks and complete consumption. No JSON codec, alternate framing, new schema or customer-data conversion was introduced. The validator tests exercise accepted/rejected shapes; the unchanged portable corpus continues executing.
  • The original failure is reproduced through published Apache, not inferred from changed source: HTTP 200 with PHP startup warning at 64 MiB, followed by OOM with an INI-only override. Exact-limit/concurrent HTTP execution, bounded heap/cgroup behavior and cold database/process recovery pass on the implementation. This is the causal transport regression; a small counted wire fixture would not prove it.

268681d keeps all immutable fixture and supplied wire-proof checks. It reports payload-related edits for review when no new wire fixture is appropriate; it does not claim any new wire-proof execution. All 71 policy tests pass, including rejection of malformed PHP, fixture mutation/duplicate/dormant evidence, continued proof verification for new wire fixtures, and unchanged growth enforcement outside Server. No exemptions, new fixture format or proxy generation were added. A final built-image check is running before merge/release.

@rmcdaniel
rmcdaniel marked this pull request as ready for review September 8, 2026 09:26
@rmcdaniel
rmcdaniel merged commit 59b455d into main Sep 8, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants