feat(session-ingest): add feature-flagged direct ingest#4480
feat(session-ingest): add feature-flagged direct ingest#4480pandemicsyn wants to merge 5 commits into
Conversation
Code Review SummaryStatus: No Issues Found | Recommendation: Merge Executive SummaryReviewed the new dark-launched direct session-ingest path (rollout gating, bounded stream reading, DO RPC call, and legacy fallback) and found no high-confidence security, correctness, or breaking-API issues in the changed code. Files Reviewed (16 files)
Reviewed by gpt-5.6-sol-20260709 · Input: 19.8K · Output: 1.7K · Cached: 18.6K Review guidance: REVIEW.md from base branch |
|
Low, Functional: The direct path surfaces synchronous rejections that the legacy queue path did not. An under-declared For selected users this changes what the ingest client can observe. If the CLI/cloud-agent treats a non-200 ingest response as a hard error (aborting the sync or surfacing an error), behavior differs from today for that cohort. Blast radius is limited by the allowlist and 0% default, so this is mainly a rollout gate: please confirm the ingest client tolerates 400/413/404 before widening the percentage. |
| actualBytes: null, | ||
| items: null, | ||
| }), | ||
| reason: 'declared_bytes_exceeded', |
There was a problem hiding this comment.
Nit, Functional: This log hardcodes reason: 'declared_bytes_exceeded', but readBoundedStream can return limit: 'configured_cap' as well as 'declared_bytes'. It is unreachable today because the route already rejects contentLength > maxBytes earlier as oversized_body, so the label is accurate for now. If that earlier guard ever moves, this telemetry would silently mislabel a cap overflow. Consider deriving the reason from buffered.limit so the log stays correct regardless of the upstream guards.
Summary
POST /api/session/:sessionId/ingestpayloads so eligible requests can persist through one synchronousSessionIngestDO.ingest()RPC before returning.Content-Length, oversized/offloaded or multi-chunk envelopes, and direct RPC failures.--include-runtime=false, matching services such as Gastown so checked-in binding diffs exclude bundled runtime declarations.Verification
Visual Changes
N/A
Reviewer Notes
florian/chore/session-ingest-direct-prepuntil PR 1 merges.DIRECT_INGEST_PERCENT=0, empty allowlist, and a 4 MiB hard cap. Invalid config closes the gate.direct_ingest_fallback.worker-configuration.d.tsnow contains only project bindings; runtime types come from@cloudflare/workers-typesintsconfig.json. (matches gas town, and should help cut down on future churn i think)wtf is this actually doing?
Session ingest is how the CLI/cloud agent sends session data to cloud, including session metadata, messages, parts, diffs, and status changes.
With the feature flag off, which is the default, requests follow the existing durable path: stage the request body in R2, enqueue a queue message, then let the queue consumer validate, chunk, and write items into the per-session Durable Object.
When the feature is enabled for a user and the request is small enough, the route validates the buffered body and writes it to the Durable Object once before returning 200, so reads immediately after the POST can see the new data. Anything outside that conservative envelope falls back to the existing R2 plus queue path.
flowchart TD A[POST session ingest] --> B[Validate session access] B --> C{Feature gate and envelope eligible?} C -- No --> L[Legacy: stage body in R2] L --> Q[Queue message] Q --> W[Consumer validates and chunks] W --> D[SessionIngestDO persists items] C -- Yes --> V[Buffer <= 4 MiB and validate] V -- Malformed --> R400[400, no writes] V -- Empty or no valid items --> R200[200 no-op] V -- Offload or multi-chunk --> L V -- Eligible --> D2[One SessionIngestDO RPC] D2 -- Accepted --> M[Best-effort metadata update] D2 -- Tombstoned --> R404[404] D2 -- Throws --> L M --> OK[200]