feat(notifications): wire on_ai_processed / on_task_failed trigger events - #67
Conversation
…ents WIRING_GAP_LEDGER W2: the model comment promised trigger_event of on_new_record | on_ai_processed | on_task_failed but the schema Literal only allowed on_new_record and dispatch_notifications() had no producer for any other value (a rule saved with another string was rejected at the schema layer — loudly, but the promised events stayed impossible). - schemas/notification: Literal now accepts all three values (Create + Update); arbitrary strings still rejected (422) - notifier_dispatch: dispatch_notifications() gains failure_payload — with no collected records and a failure payload, a synthetic (never-persisted) record carries error/error_type into the normal rule-match/send pipeline, so on_task_failed fires without any collected items - pipeline: step 5 fires on_ai_processed when AI enrichment ran (ai_count>0) after the existing on_new_record dispatch; both permanent collect-failure paths call a new best-effort _notify_task_failed() helper (error + error_type + task_id), guarded by enable_notifications and never masking the original failure Tests: schema accepts 3 values / rejects arbitrary (Create+Update), dispatch event-scoped rule matching for on_ai_processed, on_task_failed synthetic payload with error fields, pipeline wiring (failure fires _notify_task_failed with error/error_type; AI run fires both events). 42 passed on affected suites; ruff errors unchanged vs baseline (19).
|
✅ Health of changed files: 5.1 → 5.6 (+0.5) 📋 At a glance Files & modules (2)
✅ Health gate: passed 📌 Before you merge
🎯 Blast radius (symbols whose signature this PR changed, and who calls them)
🔎 More signals (2)🗺️ Change map flowchart LR
subgraph PR ["Changed in this PR (3 with dependents)"]
f_backend_pipeline_notifier_dispatch_py["backend/pipeline/notifier_dispatch.py 🔥"]:::changed
f_backend_pipeline_pipeline_py["backend/pipeline/pipeline.py 🔥"]:::changed
f_backend_schemas_notification_py["backend/schemas/notification.py 🔥"]:::changed
end
f_backend_worker_tasks_py["backend/worker/tasks.py"]
f_backend_pipeline_notifier_dispatch_py --> f_backend_worker_tasks_py
f_backend_workflow_webhook_delivery_py["backend/workflow/webhook_delivery.py"]
f_backend_pipeline_notifier_dispatch_py --> f_backend_workflow_webhook_delivery_py
f_backend_api_v1___init___py[".../v1/__init__.py"]
f_backend_pipeline_pipeline_py --> f_backend_api_v1___init___py
f_backend_channels_rss_channel_py["backend/channels/rss_channel.py"]
f_backend_pipeline_pipeline_py --> f_backend_channels_rss_channel_py
f_backend_channels_skill_channel_py["backend/channels/skill_channel.py"]
f_backend_pipeline_pipeline_py --> f_backend_channels_skill_channel_py
f_backend_config_py["backend/config.py"]
f_backend_pipeline_pipeline_py --> f_backend_config_py
f_backend_api_v1_notifications_py[".../v1/notifications.py"]
f_backend_schemas_notification_py --> f_backend_api_v1_notifications_py
more(["+3 more dependents"])
PR --> more
t_tests_unit_pipeline_test_notifier_dispatch_errors_py(["✅ .../pipeline/test_notifier_dispatch_errors.py"]):::guard
t_tests_unit_pipeline_test_notifier_dispatch_errors_py -.-> f_backend_pipeline_notifier_dispatch_py
t_tests_unit_pipeline_test_legacy_db_sink_py(["✅ .../pipeline/test_legacy_db_sink.py"]):::guard
t_tests_unit_pipeline_test_legacy_db_sink_py -.-> f_backend_pipeline_pipeline_py
classDef changed fill:#dbeafe,stroke:#1d4ed8,color:#1e3a5f
classDef warn fill:#fef3c7,stroke:#b45309,color:#78350f
classDef guard fill:#dcfce7,stroke:#15803d,color:#14532d
Solid arrows: code that imports the changed files (10 direct dependents, from the last indexed snapshot). Dashed: history/tests. 🔥 Hotspots touched (5)
2 more
👀 Suggested reviewers @2233admin 📊 See the full report for this PR |
|
Warning Review limit reached
Next review available in: 38 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (6)
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. Comment |
Summary
WIRING_GAP_LEDGER W2: the model comment promised
trigger_eventofon_new_record | on_ai_processed | on_task_failedbut the schema Literal only allowedon_new_recordanddispatch_notifications()had no producer for any other value — a rule saved with another string was rejected at the schema layer, but the promised events stayed impossible.Changes
schemas/notification: Literal now accepts all three values (Create + Update); arbitrary strings still rejected (422)notifier_dispatch:dispatch_notifications()gainsfailure_payload— with no collected records and a failure payload, a synthetic (never-persisted) record carries error/error_type into the normal rule-match/send pipeline, soon_task_failedfires without any collected itemspipeline: step 5 fireson_ai_processedwhen AI enrichment ran (ai_count>0) after the existingon_new_recorddispatch; both permanent collect-failure paths call a new best-effort_notify_task_failed()helper (error + error_type + task_id), guarded byenable_notificationsand never masking the original failureTest Plan
on_ai_processed(on_new_record rule does NOT fire)on_task_failedsynthetic payload with error fields_notify_task_failedwith error/error_type; AI run fires both events42 passed on affected suites; ruff errors unchanged vs baseline (19).