Throttle sdp-expectation-notifications hook and surface backstop notification controls - #17
Merged
Conversation
…fication controls Ground the revision in two days of live measurement (2026-07-17/18, serverless SDP, non-development-mode target): expectation counts arrive once per microbatch, so the v1.11.0 hook notified once per file on a backlog, repeated everything on full refresh, and fired on every arriving file in continuous mode. Hook: two-layer time-aware throttle (in-memory always; optional durable marker files under an existing UC Volume at <state_dir>/dq_notify_state/<pipeline>/<dataset>__<expectation>.json), scoped per pipeline from the event origin, fail-open on any state error. Webhook payload formats for Slack (validated end to end), Teams (doc-confirmed), and generic receivers; webhook URL resolution via dbutils.secrets.get with graceful degradation on a missing scope. New state_volume_path prompt (placeholder = in-memory only); no volume resource shipped on purpose. Backstop: notify_on_ok true as the new default (one recovery email closes the state-change masking window), retrigger_seconds and destination_id shipped as commented, documented options, plus the measured ERROR-state behavior (emails every evaluation until fixed). Docs corrected from measurement: hook_progress records ENABLED/FAILED/DISABLED (not enable-only), the teardown grace budget is seconds (a 20s/event hook lost 6 of 6 queued notifications under natural teardown), INSERT INTO from a hook fails with UNSUPPORTED_SPARK_SQL_COMMAND, volume file I/O works except append, and a no-new-data update emits no expectation events at all. Tests: throttle decision logic exercised offline by exec-ing the pure helpers against a temp state dir (window suppression, durability across simulated process restarts, per-pipeline scoping, marker overwrite, zero disables, empty state dir writes nothing), payload formats and guarded secret resolution asserted, spark.sql AST guard retained. Full suite: 2446 passed, 163 skipped. E2E validated on a live workspace from this working tree.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issue
Closes #(none: notification-hygiene follow-up to the v1.11.0 asset, driven by live investigation)
Summary
The shipped sdp-expectation-notifications hook notifies on every qualifying flow_progress event, and the platform emits expectation counts once per microbatch, so one failing expectation floods on multi-batch, full-refresh, and continuous pipelines (measured live: 4 notifications for one expectation in one update; a fresh event within ~70s of every arriving file in continuous mode). This PR revises the asset around a measured, two-lane design: a time-aware throttled hook (fast lane) and the backstop alert promoted to the guaranteed lane with its platform-native notification controls surfaced and documented.
Every design decision traces to live evidence from 2026-07-17/18 (serverless SDP, non-development-mode target, Free Edition playground); the findings dossier lives outside the repo and the README carries the numbers.
Changes
dq_notify.throttle_seconds(default 3600; 0 restores old behavior). In-memory layer always on (timestamp-based, not a seen-set: continuous pipelines keep one process alive for days); optional durable marker files under<dq_notify.state_dir>/dq_notify_state/<pipeline>/<dataset>__<expectation>.jsonin an existing UC Volume (one human-readable JSON per expectation, overwritten in place). Per-pipeline scoping comes from the event's own origin, zero config, no cross-pipeline suppression. Fail-open on any state error.dq_notify.channel_format= slack (validated E2E: secret scope -> dbutils.secrets.get -> hook -> channel message, HTTP 200) | teams (documented Adaptive Card envelope, marked doc-confirmed, not live-tested) | generic. Secret-scope URL resolution with graceful degradation on a missing scope (validated);{{secrets/...}}config interpolation documented as non-functional in SDP pipeline configuration (observed).state_volume_path(placeholder default = in-memory throttle only). Deliberately no volume resource: operational state should outlive any one bundle.notify_on_ok: truenew default (measured: exactly one email per state transition and one recovery email; the recovery email closes the masking window).retrigger_secondsanddestination_idship commented with measured semantics. Measured ERROR behavior documented (emails every evaluation until fixed).Change Area
assets/<name>/)Configuration Axes Affected
Testing
pytest tests/ -V): 2446 passed, 163 skippedAsset Changes
library/helpers.tmplor other assets)tests/configs/assets/sdp_expectation_notifications.jsonupdated with the new promptLive E2E validation (2026-07-18, playground, from this branch's working tree)
Not merged pending maintainer review.