50
50
SLOW_CONDITIONS ,
51
51
Condition ,
52
52
)
53
+ from sentry .workflow_engine .models .workflow_data_condition_group import WorkflowDataConditionGroup
53
54
from sentry .workflow_engine .processors .action import filter_recently_fired_workflow_actions
54
55
from sentry .workflow_engine .processors .data_condition_group import (
55
56
evaluate_data_conditions ,
56
57
get_slow_conditions_for_groups ,
57
58
)
58
- from sentry .workflow_engine .processors .detector import get_detector_by_event
59
+ from sentry .workflow_engine .processors .detector import get_detectors_by_groupevents_bulk
59
60
from sentry .workflow_engine .processors .log_util import log_if_slow , track_batch_performance
60
61
from sentry .workflow_engine .processors .workflow import (
61
62
WORKFLOW_ENGINE_BUFFER_LIST_KEY ,
62
- evaluate_workflows_action_filters ,
63
+ evaluate_action_filters ,
63
64
)
64
65
from sentry .workflow_engine .processors .workflow_fire_history import create_workflow_fire_histories
65
66
from sentry .workflow_engine .tasks .actions import build_trigger_action_task_params , trigger_action
@@ -567,6 +568,27 @@ def get_group_to_groupevent(
567
568
return group_to_groupevent
568
569
569
570
571
+ def get_dcgs_by_group (
572
+ groups_to_fire : dict [GroupId , set [DataConditionGroup ]],
573
+ event_data : EventRedisData ,
574
+ dcg_type : DataConditionHandler .Group ,
575
+ ) -> dict [GroupId , set [DataConditionGroup ]]:
576
+ """
577
+ Extract DataConditionGroups from groups_to_fire, grouped by group ID, for a particular DataConditionGroup type (e.g. workflow trigger)
578
+ trigger_group_to_dcg_model is the mapping from DataConditionGroup type to DataConditionGroup id to Workflow id
579
+ Returns a dict mapping GroupId to set of DCGs.
580
+ """
581
+ workflow_dcg_ids = set (event_data .trigger_group_to_dcg_model [dcg_type ].keys ())
582
+
583
+ workflow_dcgs_by_group = {}
584
+ for group_id , dcgs in groups_to_fire .items ():
585
+ workflow_dcgs = {dcg for dcg in dcgs if dcg .id in workflow_dcg_ids }
586
+ if workflow_dcgs :
587
+ workflow_dcgs_by_group [group_id ] = workflow_dcgs
588
+
589
+ return workflow_dcgs_by_group
590
+
591
+
570
592
@sentry_sdk .trace
571
593
def fire_actions_for_groups (
572
594
organization : Organization ,
@@ -585,6 +607,27 @@ def fire_actions_for_groups(
585
607
},
586
608
)
587
609
610
+ workflow_triggers = get_dcgs_by_group (
611
+ groups_to_fire , event_data , DataConditionHandler .Group .WORKFLOW_TRIGGER
612
+ )
613
+ action_filters = get_dcgs_by_group (
614
+ groups_to_fire , event_data , DataConditionHandler .Group .ACTION_FILTER
615
+ )
616
+ all_workflow_triggers = set ().union (* list (workflow_triggers .values ()))
617
+
618
+ # Bulk fetch detectors
619
+ event_id_to_detector = get_detectors_by_groupevents_bulk (list (group_to_groupevent .values ()))
620
+
621
+ # Bulk fetch action filters for workflow triggers
622
+ workflows = Workflow .objects .filter (when_condition_group_id__in = all_workflow_triggers )
623
+
624
+ dcg_to_workflow = {
625
+ wdcg .condition_group : wdcg .workflow
626
+ for wdcg in WorkflowDataConditionGroup .objects .select_related (
627
+ "workflow" , "condition_group"
628
+ ).filter (workflow__in = workflows )
629
+ }
630
+
588
631
total_actions = 0
589
632
with track_batch_performance (
590
633
"workflow_engine.delayed_workflow.fire_actions_for_groups.loop" ,
@@ -594,42 +637,45 @@ def fire_actions_for_groups(
594
637
for group , group_event in group_to_groupevent .items ():
595
638
with tracker .track (str (group .id )), log_context .new_context (group_id = group .id ):
596
639
workflow_event_data = WorkflowEventData (event = group_event , group = group )
597
- detector = get_detector_by_event (workflow_event_data )
598
-
599
- workflow_triggers : set [DataConditionGroup ] = set ()
600
- action_filters : set [DataConditionGroup ] = set ()
601
- for dcg in groups_to_fire [group .id ]:
602
- if (
603
- dcg .id
604
- in event_data .trigger_group_to_dcg_model [
605
- DataConditionHandler .Group .WORKFLOW_TRIGGER
606
- ]
607
- ):
608
- workflow_triggers .add (dcg )
609
- elif (
610
- dcg .id
611
- in event_data .trigger_group_to_dcg_model [
612
- DataConditionHandler .Group .ACTION_FILTER
613
- ]
614
- ):
615
- action_filters .add (dcg )
616
-
617
- # process workflow_triggers
618
- workflows = set (
619
- Workflow .objects .filter (when_condition_group_id__in = workflow_triggers )
620
- )
640
+ detector = event_id_to_detector .get (group_event .event_id )
641
+
642
+ if detector is None :
643
+ logger .warning (
644
+ "No detector found for event, skipping" ,
645
+ extra = {
646
+ "event_id" : group_event .event_id ,
647
+ "group_id" : group .id ,
648
+ },
649
+ )
650
+ continue
651
+
652
+ workflow_triggers_for_group = workflow_triggers .get (group .id , set ())
653
+ action_filters_for_group = action_filters .get (group .id , set ())
621
654
622
655
with log_if_slow (
623
656
logger ,
624
657
"workflow_engine.delayed_workflow.slow_evaluate_workflows_action_filters" ,
625
658
extra = {"event_data" : workflow_event_data },
626
659
threshold_seconds = 1 ,
627
660
):
628
- workflows_actions = evaluate_workflows_action_filters (
629
- workflows , workflow_event_data
661
+ # Process workflow filters for passing trigger groups
662
+ triggered_workflow_ids = {
663
+ event_data .dcg_to_workflow [dcg .id ] for dcg in workflow_triggers_for_group
664
+ }
665
+
666
+ filter_dcg_to_workflow : dict [DataConditionGroup , Workflow ] = {
667
+ dcg : workflow
668
+ for dcg , workflow in dcg_to_workflow .items ()
669
+ if workflow .id in triggered_workflow_ids
670
+ }
671
+
672
+ workflows_actions = evaluate_action_filters (
673
+ workflow_event_data ,
674
+ filter_dcg_to_workflow ,
630
675
)
676
+
631
677
filtered_actions = filter_recently_fired_workflow_actions (
632
- action_filters | workflows_actions , workflow_event_data
678
+ action_filters_for_group | workflows_actions , workflow_event_data
633
679
)
634
680
create_workflow_fire_histories (detector , filtered_actions , workflow_event_data )
635
681
@@ -647,7 +693,7 @@ def fire_actions_for_groups(
647
693
logger .debug (
648
694
"workflow_engine.delayed_workflow.triggered_actions" ,
649
695
extra = {
650
- "workflow_ids" : [ workflow . id for workflow in workflows ] ,
696
+ "workflow_ids" : triggered_workflow_ids ,
651
697
"actions" : [action .id for action in filtered_actions ],
652
698
"event_data" : workflow_event_data ,
653
699
"event_id" : event_id ,
0 commit comments