-
Notifications
You must be signed in to change notification settings - Fork 4.6k
refactor(webhook): event filtering to support separate query paths for event_id and object_id filters #10402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…r event_id and object_id filters
Changed Files
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #10402 +/- ##
=======================================
Coverage ? 6.46%
=======================================
Files ? 1251
Lines ? 311920
Branches ? 0
=======================================
Hits ? 20163
Misses ? 291757
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| let events = | ||
| match account { | ||
| MerchantAccountOrProfile::MerchantAccount(merchant_account) => store | ||
| .list_initial_events_by_merchant_id_primary_object_or_initial_attempt_id( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one of ObjectID or EventID will be ever sent, there would be no scenario where both are provided.It would be better to split this into two separate functions list_initial_events_by_merchant_id_primary_object_id and list_initial_events_by_merchant_id_initial_attempt_id
| { | ||
| return Err(report!(errors::ApiErrorResponse::PreconditionFailed { | ||
| message: | ||
| "Either only `object_id` or `event_id` must be specified, or one or more of \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "Either `object_id` alone, or `event_id` alone, or one or more of \ |
…/hyperswitch into webhooks_selective_search
| conn: &PgPooledConn, | ||
| merchant_id: &common_utils::id_type::MerchantId, | ||
| initial_attempt_id: &str, | ||
| ) -> StorageResult<Vec<Self>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
list_initial_attempts_by_merchant_id_initial_attempt_id will always give out a single event. The return type can be Option<Self> instead of Vec<Self>.
crates/router/src/db/events.rs
Outdated
| && event.initial_attempt_id.as_deref() == Some(&event.event_id) | ||
| && event.initial_attempt_id.as_deref() == Some(initial_attempt_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can't we just check for the event_id to be equal to initial_attempt_id?
…etch accurate data
…hooks_selective_search
…n using `try_join_all`
e109fe7
Type of Change
Description
This PR enhances webhook event search functionality by adding selective search capabilities with single point search and object-based filtering options.
Key Features Added:
event_idorobject_idfor precise event retrievalEventListConstraintswithobject_idandevent_idparametersAdditional Changes
Modified Files:
crates/api_models/src/webhook_events.rs- Added EventIdFilter variant to enumcrates/router/src/types/transformers.rs- Implemented validation and filter separation logiccrates/diesel_models/src/query/events.rs- Enhanced database queries with optional parameterscrates/router/src/db/events.rs- Updated event interface trait signaturescrates/router/src/db/kafka_store.rs- Updated KafkaStore implementationcrates/router/src/core/webhooks/webhook_events.rs- Updated filter matching logicMotivation and Context
Problem Solved:
event_idandobject_id, leading to suboptimal query performanceSolution:
ObjectIdFiltervsEventIdFilterto optimize query performanceevent_idsearch now returns exactly one event as expectedHow did you test it?
event_id:Response:
{ "events": [ { "event_id": "evt_300000000000000000000000000000016", "merchant_id": "merchant_1757947392", "profile_id": "pro_Bp8XDEMYBxHgue23rXYw", "object_id": "pay_3000005", "event_type": "dispute_challenged", "event_class": "disputes", "is_delivery_successful": false, "initial_attempt_id": "evt_300000000000000000000000000000016", "created": "2025-10-15T13:15:00.000Z" } ], "total_count": 1 }Verifying the filter search for the object_id:
Response:
{ "events": [ { "event_id": "evt_300000000000000000000000000000016", "merchant_id": "merchant_1757947392", "profile_id": "pro_Bp8XDEMYBxHgue23rXYw", "object_id": "pay_3000005", "event_type": "dispute_challenged", "event_class": "disputes", "is_delivery_successful": false, "initial_attempt_id": "evt_300000000000000000000000000000016", "created": "2025-10-15T13:15:00.000Z" }, { "event_id": "evt_300000000000000000000000000000001", "merchant_id": "merchant_1757947392", "profile_id": "pro_Bp8XDEMYBxHgue23rXYw", "object_id": "pay_3000005", "event_type": "payment_succeeded", "event_class": "payments", "is_delivery_successful": true, "initial_attempt_id": "evt_300000000000000000000000000000001", "created": "2025-10-15T10:00:00.000Z" }, { "event_id": "evt_300000000000000000000000000000005", "merchant_id": "merchant_1757947392", "profile_id": "pro_Bp8XDEMYBxHgue23rXYw", "object_id": "pay_3000005", "event_type": "payment_partially_authorized", "event_class": "payments", "is_delivery_successful": true, "initial_attempt_id": "evt_300000000000000000000000000000005", "created": "2025-09-19T14:20:00.000Z" }, { "event_id": "evt_300000000000000000000000000000004", "merchant_id": "merchant_1757947392", "profile_id": "pro_Bp8XDEMYBxHgue23rXYw", "object_id": "pay_3000005", "event_type": "payment_cancelled", "event_class": "payments", "is_delivery_successful": false, "initial_attempt_id": "evt_300000000000000000000000000000004", "created": "2025-09-18T13:15:00.000Z" } ], "total_count": 4 }Validation Test - Both filters provided simultaneously:
Response:
{ "error": { "type": "invalid_request", "message": "Cannot specify both `object_id` and `event_id`. Please provide only one.", "code": "IR_16" } }Edge Case: Searching with event_id by selecting object_id and vice versa
Response:
{"events":[],"total_count":0}Checklist
cargo +nightly fmt --allcargo clippy