Skip to content

feat(apify): scrape alerts fire only on genuinely new posts (diff against stored posts)#759

Open
sweetmantech wants to merge 1 commit into
mainfrom
feat/scrape-alert-newness-diff
Open

feat(apify): scrape alerts fire only on genuinely new posts (diff against stored posts)#759
sweetmantech wants to merge 1 commit into
mainfrom
feat/scrape-alert-newness-diff

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Kills the alert false positives: the notifier sent "new posts" whenever a scrape returned any posts — no diff against what's stored — so every scrape re-announced the profile's recent feed. Evidence on recoupable/chat#1855: 6 of 7 alerts to one customer in one day announced posts that were 2–10 days old and already in the database.

Tracking issue: recoupable/chat#1855 (PR #3 of 6 — independent; biggest notification-volume win).

What changed

  • lib/socials/filterNewPostUrls.ts (new, reusable across platforms): given candidate post URLs, returns those with no existing posts row. Documented constraint: must run before the upsert (afterwards nothing is distinguishable as new).
  • lib/apify/instagram/handleInstagramProfileScraperResults.ts: computes the diff pre-upsert and only sends the alert when ≥1 URL is genuinely new. Persistence is unaffected — posts/socials/social_posts/follow-up scrapes run exactly as before; only the notification is gated.

Tests (RED→GREEN)

  • filterNewPostUrls: known-vs-new partition, all-new passthrough, empty-input short-circuit (no query).
  • Handler: new case — all posts already stored → no email, everything else persists; existing happy-path (new posts → email) unchanged.
  • Suites: vitest run lib/socials lib/apify/instagram13 files, 63 tests passed; eslint clean.

Relationship to the digest PRs

The digest aggregation (PR #4) consumes this same helper per platform. This PR is deliberately shippable alone for immediate relief on the current per-platform email.

🤖 Generated with Claude Code


Summary by cubic

Stop Instagram scrape alerts from re-announcing old posts by diffing scraped URLs against stored posts before upsert. This eliminates false-positive “new post” emails (recoupable/chat#1855).

  • Bug Fixes
    • Added filterNewPostUrls and used it in the Instagram handler before upsert to identify genuinely new URLs.
    • Gated alert emails on a non-empty diff; persistence and follow-up scrapes remain unchanged, with tests covering the helper and no-email path.

Written for commit 360268b. Summary will update on new commits.

Review in cubic

… posts first

The Instagram scrape alert fired whenever a scrape returned posts, with no
comparison against posts already stored — every scrape re-announced the
profile's recent feed as new (observed: 6 of 7 alerts in one day announced
posts up to 10 days old). New reusable filterNewPostUrls diffs candidate
URLs against posts BEFORE upsert; the alert is gated on a non-empty result.
Persistence unchanged (recoupable/chat#1855, PR #3 of 6).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
api Ready Ready Preview Jul 6, 2026 9:57pm

Request Review

@cursor

cursor Bot commented Jul 6, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@sweetmantech, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 24 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f44f7090-a7f2-42f2-926e-6aaadd5b1bf4

📥 Commits

Reviewing files that changed from the base of the PR and between 7ed9338 and 360268b.

⛔ Files ignored due to path filters (2)
  • lib/apify/instagram/__tests__/handleInstagramProfileScraperResults.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/socials/__tests__/filterNewPostUrls.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
📒 Files selected for processing (2)
  • lib/apify/instagram/handleInstagramProfileScraperResults.ts
  • lib/socials/filterNewPostUrls.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/scrape-alert-newness-diff

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot 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.

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.
Architecture diagram
sequenceDiagram
    participant ApifyCloud as Apify Cloud Webhook
    participant Handler as handleInstagramProfileScraperResults
    participant Filter as filterNewPostUrls (NEW)
    participant DB as Supabase (posts table)
    participant Upsert as upsertPosts / upsertSocials / upsertSocialPosts
    participant Email as sendApifyWebhookEmail
    participant FollowUp as handleInstagramProfileFollowUpRuns

    Note over ApifyCloud,FollowUp: Instragram scrape alert — NEW: only notify on genuinely new posts

    ApifyCloud->>Handler: POST /apify/instagram (scrape result)
    Handler->>Handler: Extract post URLs from latestPosts

    Note over Handler,Filter: Must run BEFORE upsert (chat#1855)
    Handler->>Filter: filterNewPostUrls(postUrls)
    Filter->>DB: getPosts({ postUrls })
    DB-->>Filter: existing posts (post_urls)
    Filter-->>Handler: newPostUrls (URLs not in DB)

    Handler->>Upsert: upsertPosts(postRows)  (all scraped URLs)
    Handler->>Handler: getPosts() to fetch upserted records

    alt newPostUrls.length > 0
        Handler->>Email: sendApifyWebhookEmail(firstResult, emails)
        Email-->>Handler: sentEmails
    else newPostUrls.length === 0
        Note over Handler: NEW: skip email — all posts already stored
    end

    Handler->>FollowUp: handleInstagramProfileFollowUpRuns(...)
    FollowUp-->>Handler: follow-up runs

    Handler-->>ApifyCloud: response (social, posts, etc.)
Loading

Auto-approved: Adds filterNewPostUrls to diff scraped URLs against stored posts, gating alert emails on genuinely new posts only. Tests pass for both the helper and the handler's no-email path.

Re-trigger cubic

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