Repository navigation
fix(cold-store-reaper): D1 sync batches sized by bound-parameter budget - #933
Conversation
…face D1 error text D1 allows at most 100 bound parameters per query, but sync-manifest batched a flat 50 rows per statement: objects has 8 columns, so the statement carried 112 params at just 14 rows and D1 rejected it (HTTP 400). Batch size is now computed per table from its column count: batch_rows = max(1, 90 // ncols), so rows x columns stays within a 90-parameter budget under the hard limit for every table. Also include the D1 API's own errors[0].message in the HTTP-failure message, so a failed sync is diagnosable from the CLI output alone.
Seed 30 extra objects (31 total) so the old flat 50-row batch would
emit one 248-parameter statement; assert every statement stays at or
under D1's 100 bound parameters, that per-table arrived row counts
match the local manifest exactly, and that objects splits into
3 statements at the 90 // 8 = 11-row batch. Verified failing on the
pre-fix code with '248 not less than or equal to 100'.
Also assert the HTTP-error message now carries the D1 API's own
error text ('fake failure' from the stub), not just the status.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 27 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Bug
cold-store sync-manifestfailed live withD1 sync failed (HTTP 400) on table objectsonce the objects table reached 14 rows. Root cause: statements batched a flatD1_SYNC_BATCH_ROWS = 50rows regardless of table shape. A statement costs rows × columns bound parameters, and D1 allows at most 100 bound parameters per query — objects has 8 columns, so 14 rows already made 112 params (50 rows would be 400).Fix
batch_rows = max(1, 90 // ncols)(D1_SYNC_PARAM_BUDGET = 90, headroom under the hard limitD1_MAX_PARAMS_PER_QUERY = 100). Resulting batches: objects 11 rows (88 params), bundles 9 (90), members 22 (88), transfer_ledger 15 (90), meta 45 (90). Applied inbuild_sync_statementsfor all five synced tables; the flat constant is gone.errors[0].messagefrom the response body, via a defensived1_error_messagehelper with a raw-body fallback), so a failure reads e.g.D1 sync failed (HTTP 400) on table objects: <D1's message> — statements already sent are idempotent upserts, re-run to resume.Tests
test_sync_many_objects_stays_under_d1_param_limit: seeds 30 extra objects (31 total) against the stubbed FakeD1 HTTP layer, asserts every statement carries ≤ 100 params, per-table arrived row counts equal the local manifest exactly, and objects splits into 3 statements at the 11-row batch.test_sync_http_error_is_clearnow also asserts the API's error text (fake failure) appears in the raised message.cold_store.py— the regression test withAssertionError: 248 not less than or equal to 100, exactly the production failure mode.Stdlib only; no live Cloudflare/Google calls in tests.
Need help on this PR? Tag
@codesmith-botwith what you need.