fix(ingestion): watermark collaboration staging on extract time, not business date - #1273
Conversation
…business date
The incremental connector-staging models for collaboration (zoom / m365 /
slack / zulip) gated incrementality on a forward-only business-date watermark:
WHERE business_date > (SELECT max(business_date) - INTERVAL 3 DAY FROM this)
This permanently strands backfilled / late-arriving bronze history: once the
target's max business date advances, any source rows whose business date is
older than that max never re-enter the model. On the virtuozzo cluster this
silently truncated Zoom meeting activity to the last ~week (bronze held the
full Jan–Jun history) and Slack chat to late-March onward, so the product's
"Meeting Hours" metric read ~19h/month ≈ ~17h/week for a user whose true
month was ~67h.
Fix: gate on the source EXTRACT time instead. Re-pulled / late rows always
carry a fresh `_airbyte_extracted_at`, so we reprocess every business date
that has any bronze row extracted within 3 days of the newest extract. The
whole date is re-derived from full bronze, which keeps the Zoom per-day
aggregate correct even when a day's participants arrive across several sync
batches. Pure WHERE change: no new columns, so union_by_tag feeders stay
schema-aligned and no --full-refresh redeploy is required.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThis PR updates eight dbt incremental collaboration models (M365 chat/email/meeting/document activity, Slack chat, Zoom meeting, Zulip chat) to use source extraction timestamps ( ChangesIncremental Watermark Refactoring
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
Problem
The incremental connector-staging models for collaboration gated incrementality on a forward-only business-date watermark:
{% if is_incremental() %} WHERE business_date > (SELECT max(business_date) - INTERVAL 3 DAY FROM {{ this }}) {% endif %}This permanently strands backfilled / late-arriving bronze history: once the target's max business date advances, any source rows whose business date is older than that max never re-enter the model — even though they are present in bronze.
Observed impact (virtuozzo)
A user's Meeting Hours read ~19h/month ≈ ~17h/week — month ≈ week — for someone whose true month was ~67h.
Root cause traced layer by layer:
bronze_zoom.participantsstaging.zoom__collab_meeting_activitySo the monthly metric was effectively M365 (full) + Zoom (last week only). Slack chat had the same gap (bronze from Jan, staging from late-Mar). M365/Cursor/Claude happened not to manifest only because their bronze never gained pre-existing history after the watermark advanced — the code is equally fragile.
Fix
Gate on the source extract time instead of the business date. Re-pulled / late rows always carry a fresh
_airbyte_extracted_at, so we reprocess every business date that has any bronze row extracted within 3 days of the newest extract:{% if is_incremental() %} AND ( (SELECT count() FROM {{ this }}) = 0 OR business_date IN ( SELECT DISTINCT business_date FROM {{ source(...) }} WHERE _airbyte_extracted_at > (SELECT max(_airbyte_extracted_at) FROM {{ source(...) }}) - INTERVAL 3 DAY ) ) {% endif %}GROUP BY email, date) stays correct even when a day's participants arrive across several sync batches — a plain_airbyte_extracted_at > maxrow-watermark (as used by the 1:1 git/CRM staging models) would undercount aggregates here, which is why this uses a date-reprocess form.WHEREchange — no new output columns, sounion_by_tagfeeders stay schema-aligned and no--full-refreshredeploy is required.Files (8 collaboration staging models)
zoom__collab_meeting_activitym365__collab_meeting_activity,m365__collab_chat_activity,m365__collab_email_activity,m365__collab_document_activity_onedrive,m365__collab_document_activity_sharepointslack__collab_chat_activityzulip_proxy__collab_chat_activityAlready remediated on virtuozzo
A one-off
dbt run --full-refreshover the affected staging + silver chain has been applied:staging.zoom__collab_meeting_activitywent 8 → 127 days, and the user's monthly Meeting Hours corrected 19.82h → 66.77h with no duplicates (silverunion_by_tagQUALIFY-dedup + gold view).Follow-up (same anti-pattern, not in this PR)
The AI usage models carry the identical business-date watermark and should get the same fix:
cursor__ai_dev_usage,claude_admin__ai_{api,dev}_usage,claude_enterprise__ai_{assistant,dev}_usage,claude_team__ai_dev_usage,copilot__ai_{dev,org}_usage, the OpenAIto_ai_*models (max(report_date), no interval), and silverclass_focus_metrics(max(day) - 3). They are not currently manifesting on virtuozzo.🤖 Generated with Claude Code
Summary by CodeRabbit