feat(apify): one consolidated new-posts digest per scrape batch
Summary
The digest architecture for recoupable/chat#1855 (PR #4 of 6, decision: one email per scrape, all platforms): registers each platform run under a batch_id at scrape start, records completions + genuinely-new post URLs in the webhook layer, and sends one consolidated digest when the batch's last run completes.
Stacked on api#759 (newness diff — provides filterNewPostUrls); requires database#41 (batch columns) applied before this deploys. Base is #759's branch so the diff shows only this PR's work; GitHub retargets to main when #759 merges.
What changed
lib/supabase/apify_scraper_runs/(new):insertApifyScraperRuns(start-time registration),completeApifyScraperRun(completion + new URLs),selectApifyScraperRunsByBatch,selectApifyScraperRun, local row type (generated types don't carry database#41's columns yet).lib/apify/digest/(new):maybeSendScrapeDigest(the brain: all-siblings-complete gate → per-platform sections → skip-if-nothing-new),getScrapeDigestRecipients(same watcher chain the solo alert used),sendScrapeDigestEmail(BCC-only, deterministic minimal body — upgraded to the house template in PR #5).postArtistSocialsScrapeHandler: mints the batch, registers runs (with platform + social mapping via a new additiveprofileUrlonscrapeProfileUrlBatchresults); response contract unchanged (extra field stripped).apifyWebhookHandler: after each result handler, completes the run and runs the digest check; failures never fail the webhook. Schema now passes through the optionalresource.idApify already sends.- TikTok/Twitter handlers now compute + return
newPostUrls(pre-persist diff); Instagram suppresses its solo email for batch-registered runs (legacy runs keep it).
Tests (RED→GREEN)
maybeSendScrapeDigest: 4 cases — waits for incomplete siblings; one send with per-platform sections (empty platforms omitted); nothing-new sends nothing; null batch no-ops.- Webhook: completion recorded with the handler's new URLs + digest check with the run's batch id; no-run-id skips bookkeeping.
- Instagram: batch-registered run with new posts → no solo email,
newPostUrlsreturned. - Sweeps:
lib/apify+lib/artist+lib/socials→ 272 tests passed;tsc --noEmitat exact baseline parity (200 pre-existing, 0 new); eslint clean.
Merge sequencing
database#41 → api#759 → this. E2E verification (real batch scrape → one digest) planned post-merge on the tracking issue since Apify webhooks call the deployed receiver.
🤖 Generated with Claude Code
Summary by cubic
Send one consolidated new-posts digest per scrape batch across all platforms. Implements chat#1855 by batching runs, diffing genuinely new URLs, and emailing a single BCC digest when the last run completes.
-
New Features
- Adds
apify_scraper_runshelpers:upsertApifyScraperRuns(batch registration),updateApifyScraperRun(completion + new URLs),selectApifyScraperRuns(optional{ batchId }), andselectApifyScraperRun; helpers use generatedTables/TablesInserttypes. - Webhook accepts optional
resource.id, records completion withupdateApifyScraperRun, and callsmaybeSendScrapeDigest; digest errors never fail the webhook. - Digest module:
getScrapeDigestRecipients,parseNewPostUrls(safe JSONB parser),maybeSendScrapeDigest,sendScrapeDigestEmail(per‑platform sections, BCC‑only; empty platforms omitted). - TikTok/Twitter handlers return
newPostUrls(pre‑persist diff); Instagram returnsnewPostUrlsand suppresses the solo email for batch runs (legacy runs unchanged). postArtistSocialsScrapeHandlermints abatch_id, registers runs viaupsertApifyScraperRunswith platform/social mapping (fromprofileUrlinscrapeProfileUrlBatch), and returns the same response shape (extra field stripped).
- Adds
-
Migration
- Ensure
apify_scraper_runshasbatch_id,completed_at, andnew_post_urlsbefore deploying;types/database.types.tsregenerated (database#47). No API response changes.
- Ensure
Summary by CodeRabbit
-
New Features
- Added digest-based email notifications for newly scraped posts, including consolidated updates across platforms.
- Scrape runs now track batch information and newly discovered post links for better follow-up handling.
- Batch scrape results now include the original profile URL for easier reference.
-
Bug Fixes
- Improved notification behavior so per-platform emails are suppressed during batch digest runs.
- Webhook processing now continues successfully even if digest-related follow-up steps fail.