Skip to content

feat(importer): wire crawler to the rate.crawl_jobs queue - #4

Merged
JOY (JOY) merged 6 commits into
devfrom
feat/queue-wiring
Oct 7, 2026
Merged

JOY (JOY) merged 6 commits into
devfrom
feat/queue-wiring

Conversation

@JOY

Copy link
Copy Markdown
Contributor

Summary

Wires the Shopee crawler to the queue schema merged in DOS-Me PR #1027 (now live on prod - verified start/finish_crawl_run, crawl_jobs, review_flags, price_history.observation_id all present).

  • QueueDrivenShopeeCrawler (new): dequeue -> process -> ack/fail through the SECURITY DEFINER RPCs with per-claim token fencing; heartbeats during long scrapes; per-section checkpoints
  • ingestProduct(section report callback): worker checkpoints merchant/master/listing/price/reviews completion for resume granularity
  • enqueue-shopee.ts CLI: enqueue product URLs (parses i.shopId.itemId), opens a crawl run
  • run-queue-crawl.ts driver: cloned-Chrome CDP (home IP default / USE_4G=1), store warm-up before every PDP (the proven anti-risk-control recipe), drain loop, clean teardown

Verification

  • Live prod smoke: enqueue -> dequeue(attempt 1, token) -> checkpoint ok -> ack ok; re-enqueue after done creates a fresh pending job (terminal states never block recrawl)
  • tsc --noEmit clean

- QueueDrivenShopeeCrawler: claims jobs via dequeue_crawl_job, heartbeats
  long scrapes, checkpoints per-section ingest progress, acks/fails with
  the per-claim token fence - all through the SECURITY DEFINER RPCs
  (direct DML on crawl_jobs stays revoked server-side)
- ShopeeIngestionPipeline.ingestProduct accepts an optional section
  report callback (merchant/master/listing/price/reviews) so the worker
  checkpoints after each idempotent section (plan v7 section 4.1)
- Scripts/enqueue-shopee.ts: CLI to enqueue product URLs (parses
  shop/item ids, opens a crawl run)
- Scripts/run-queue-crawl.ts: full driver - cloned-Chrome CDP launch
  (home IP default, USE_4G=1 for mproxy), human-like store warm-up
  before each PDP, worker loop until queue drains, finish_crawl_run +
  browser teardown in finally

Verified against the live prod schema (migrations propagated):
enqueue -> dequeue(attempt 1, token) -> checkpoint ok -> ack ok;
re-enqueue after done correctly creates a fresh pending job (terminal
states never block recrawl). tsc clean.
@JOY
JOY (JOY) force-pushed the feat/queue-wiring branch 2 times, most recently from 1ac5e04 to aa6a1e9 Compare October 7, 2026 09:10
Codex round-1 review of the queue wiring:
- BLOCKER: a rejected heartbeat or refused ack now aborts the job with
  LEASE_LOST - the worker stops touching the listing and never logs a
  false ACKED (the true owner owns the outcome); the in-flight
  heartbeat promise is awaited on teardown
- BLOCKER: post-run cleanup awaits finish_crawl_run in try/catch (the
  PostgREST builder has no .catch); stopLocalForwarder was missing on
  the branch base because dev had unpushed Shopee commits - dev is now
  synced (c941957) and the rebased branch has it
- SHOULDs: setup after start_crawl_run is inside try/finally; kill is
  scoped to crawl profile dirs (single-driver documented); idle
  semantics document backoff-aware waiting (30s x 4); enqueue CLI exits
  non-zero on run failure, enqueue failure or skipped URLs; --max-jobs
  NaN guard; reviews-section checkpoint fires on empty review lists;
  checkpoint trail documented as observability (retries re-run the
  idempotent pipeline)
JOY added 2 commits October 7, 2026 16:17
…are catch, chained heartbeats

- re-check leaseLost after every awaited checkpoint inside the ingest
  report callback: the pipeline must not start the next section's
  writes once the lease died mid-checkpoint
- catch treats leaseLost=true as abandonment even when the work threw a
  normal error afterwards - fail_crawl_job must never run for a job
  this worker no longer owns
- heartbeats chain onto the in-flight promise so overlapping interval
  ticks cannot overwrite the tracked heartbeat (teardown awaits them all)
Codex round-3: chaining queued an unbounded heartbeat backlog when RPCs
were slow and teardown awaited all of it. A tick now no-ops while the
previous heartbeat is in flight (lease >> interval, so a skipped tick
only shortens the effective lease marginally); teardown awaits just the
one running RPC; hbInFlight resets to null on completion so the cast
workaround is gone.
Qwen review: the check-then-insert pattern is not atomic across
concurrent workers; the DB unique index arbitrates, so a 23505 (or
'duplicate key') on the reviews/price inserts is a lost dedupe race,
not a failure - warn and continue. All other errors still fail the
ingestion.
…f swallowing the batch

Codex P1: batch inserts are atomic - swallowing a 23505 dropped the
genuinely-new rows sharing the batch while the job still acked. On a
race the worker now refetches which ids exist, retries the remainder
once, and throws if rows remain unexplained.
@JOY
JOY (JOY) merged commit 461e557 into dev Oct 7, 2026
2 of 4 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.

1 participant