Skip to content

port(v2): partition-parallel drain for large sales-filter backlogs (#71 on the v2 line)#72

Merged
robrigo merged 4 commits into
atomicassets:feat/atomicassets-v2from
igorls:feat/parallel-sales-filter-drain-v2
Jun 10, 2026
Merged

port(v2): partition-parallel drain for large sales-filter backlogs (#71 on the v2 line)#72
robrigo merged 4 commits into
atomicassets:feat/atomicassets-v2from
igorls:feat/parallel-sales-filter-drain-v2

Conversation

@igorls

@igorls igorls commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Port of #71 onto feat/atomicassets-v2, so the 2.0.0 line ships with a recovery path for bulk atomicmarket_sales_filters_updates backlogs (deep catchup, bulk load, drain outage). Opened separately per the cherry-pick-to-v2 workflow used for #68/#69/#70 in 2.0.0-rc2 — happy to close either side if you prefer a different route.

Differences from #71 (content otherwise unchanged)

  • Migration renumbered 1.7.132.0.1 so it sorts after 2.0.0 and still applies to databases already initialized from the 2.0.0-rc tags.
  • Cherry-picks apply cleanly: the branch's merge-base with main is v1.7.11, its 1.7.11 migration is byte-identical to main's, and the 2.0.0 migration does not touch the drain — so the parity guarantee (recompute CTE byte-for-byte 1.7.11) holds identically here.

Validation

  • 349 integration tests passing on this branch on PostgreSQL 18 (same combo as the rc2 release testing): the full v2 suite + 9 new tests (byte-identical parity vs the stock drain via to_jsonb equality, partition scoping, offer normalization, and the advisory-lock matrix on real concurrent backends).
  • Underlying mechanism production-validated on WAX mainnet (460M assets): 8 workers drained 3.28M queued sales in 229s (~14,300/s vs ~17/s net single-flight); 504k offer rows normalized in ~7s via the new (assets_contract, offer_id) index; reader at head throughout. Details in feat(filler): opt-in partition-parallel drain for large sales-filter backlogs #71.
  • Possibly relevant for the open move sales-filter drain baseline item: if v2 ends up enqueueing move-driven changes into the same queue, the partition workers consume them transparently once they resolve to sale rows.

igorls added 4 commits June 10, 2026 00:51
…backlogs

A deep catchup or bulk load leaves atomicmarket_sales_filters_updates with a
multi-million-row backlog that the (correctly) single-flight drain clears at
random-read I/O speed - days to weeks of stale /v2/sales filters. The recompute
parallelizes perfectly across disjoint sales, so:

* update_atomicmarket_sales_filters_partition(part_count, part_index, batch):
  the 1.7.11 drain restricted to sale rows with sale_id % part_count =
  part_index. Recompute CTE block is byte-for-byte 1.7.11. Workers take the
  stock drain's advisory key SHARED (stock takes it exclusively - unchanged),
  plus an exclusive per-partition sub-lock: N workers coexist, never with the
  stock drain, duplicates no-op. Nothing runs unless an operator launches it.

* normalize_atomicmarket_sales_filters_offers(batch): converts queued offer
  rows into the equivalent queued sale rows (same resolution the stock drain
  does per batch) so workers can own them; 1.7.11 seq-guard protocol.

* index on atomicmarket_sales_filters (assets_contract, offer_id): the drain's
  offer->sales resolution was a hash join scanning the multi-GB filter
  partitions every batch containing offer rows; now index probes. Also speeds
  the stock drain.

* bin/drain-sales-filters.js [--partitions N] [--batch B]: operator runner -
  normalizes offers, runs N partition workers to empty, ANALYZEs after.

Validated against a production WAX dataset (3.9M-row backlog).
…tionale

Review follow-ups on atomicassets#71 (comment-only, no behavior change):
- Replace the loose 'pre-build under the same names' note with the actual
  ON ONLY + CREATE INDEX CONCURRENTLY + ATTACH PARTITION recipe (attachment
  matches on definition equivalence, not names) as used for the production
  validation run.
- State the plain-temp-table rationale (1.7.11 precedent: reused pool
  connections, no DROP-IF-EXISTS notice spam; the claimed (key,seq) set must
  survive across statements so a CTE chain cannot replace it; per-call DDL is
  negligible at drain cadence).
….0.1

The v2 line's migration chain is at 2.0.0 (rc tags already initialize databases
at that version), so the main-line 1.7.13 directory would sort before 2.0.0 and
never apply to them. Renumbered to 2.0.1; SQL content unchanged from PR atomicassets#71.
@igorls
igorls marked this pull request as ready for review June 10, 2026 04:08
Copilot AI review requested due to automatic review settings June 10, 2026 04:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds an opt-in, partition-parallel backlog drain for atomicmarket_sales_filters_updates, including the supporting DB functions/index, a CLI runner, and integration tests validating partition scoping, parity with the stock drain, and advisory-lock behavior.

Changes:

  • Add migration 2.0.1 implementing offer normalization + partition worker drain functions and an index to speed offer→sale resolution.
  • Add a drain-sales-filters CLI script to run parallel workers safely alongside the live filler.
  • Add integration tests covering correctness (parity), partition isolation, and lock protocol across multiple connections.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/filler/handlers/atomicmarket/sales-filters-parallel-drain.integration.test.ts New integration coverage for partition drain, normalization, and advisory-lock protocol.
src/bin/drain-sales-filters.ts New CLI script orchestrating offer normalization + parallel partition workers + ANALYZE.
definitions/migrations/2.0.1/database.sql Bumps DB version to 2.0.1 with migration context.
definitions/migrations/2.0.1/atomicmarket.sql Adds offer-id index plus normalize_* and update_*_partition functions with locking protocol.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +69 to +73
const a = await client.createFullSale();
const b = await client.createFullSale({ sale_id: Number(a.sale_id) + 1 }); // adjacent => opposite parity

const mine = Number(a.sale_id) % 2;
await client.query('SELECT update_atomicmarket_sales_filters_partition(2, $1, 5000)', [mine]);
Comment on lines +68 to +69
SET LOCAL statement_timeout = 0;
SET LOCAL lock_timeout = '60s';

@robrigo robrigo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review (FACINGS) — LGTM.

  • Port fidelity verified mechanically: normalized diff-of-diffs vs #71 shows the only differences are the port-note comments; SQL, runner, and tests are content-identical.
  • 2.0.1 numbering is exactly right for this line — it sorts after 2.0.0, so databases already initialized from the 2.0.0-rc tags (jungle4 is at dbinfo.version = 2.0.0 today) will still pick it up. A 1.7.13 here would have been silently skipped on those DBs.
  • Ran on PostgreSQL 18 against this branch: full v2-line integration 349 passing (340 + the 9 new parallel-drain tests, running under the 2.0.1 banner), typecheck clean.

Heads-up, not a blocker: this PR gets no CIci.yaml only triggers on PRs to main, and this targets feat/atomicassets-v2. The local run above is currently the only gate. Worth adding feat/atomicassets-v2 to the pull_request.branches list (here or as a follow-up) so the v2 line gets PR CI.

@robrigo
robrigo requested a review from Copilot June 10, 2026 12:59
@robrigo
robrigo merged commit e592516 into atomicassets:feat/atomicassets-v2 Jun 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated no new comments.

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.

3 participants