@@ -911,6 +911,67 @@ def send_webhooks_notification(event: str, user_id: int | None = None, **kwargs:
911911 get_manager_class_instance ()._get_manager_instance ("webhooks" ).send_webhooks_notification (event , user = user , ** kwargs )
912912
913913
914+ @app .task
915+ def async_create_notification (
916+ event : str ,
917+ engagement_id : int | None = None ,
918+ product_id : int | None = None ,
919+ product_type_id : int | None = None ,
920+ finding_id : int | None = None ,
921+ test_id : int | None = None ,
922+ ** kwargs : dict ,
923+ ) -> None :
924+ # Re-fetch by id so the recipient-enumeration query and per-user Alert writes
925+ # run in the worker rather than the request thread.
926+ # Fetch most-specific first and derive parent objects from the already-loaded
927+ # select_related chain to avoid redundant queries. For example, fetching a
928+ # Test with select_related("engagement__product") covers all three objects in
929+ # one query, so engagement_id and product_id don't need separate fetches.
930+ fetched_engagement = None
931+ fetched_product = None
932+
933+ if test_id is not None :
934+ test = Test .objects .filter (pk = test_id ).select_related ("engagement__product" ).first ()
935+ if test is None :
936+ return
937+ kwargs ["test" ] = test
938+ fetched_engagement = test .engagement
939+ fetched_product = test .engagement .product
940+
941+ if engagement_id is not None :
942+ if fetched_engagement is not None :
943+ kwargs ["engagement" ] = fetched_engagement
944+ else :
945+ engagement = Engagement .objects .filter (pk = engagement_id ).select_related ("product" ).first ()
946+ if engagement is None :
947+ return
948+ kwargs ["engagement" ] = engagement
949+ fetched_product = engagement .product
950+
951+ if product_id is not None :
952+ if fetched_product is not None :
953+ kwargs ["product" ] = fetched_product
954+ else :
955+ product = Product .objects .filter (pk = product_id ).first ()
956+ if product is None :
957+ return
958+ kwargs ["product" ] = product
959+
960+ if product_type_id is not None :
961+ product_type = Product_Type .objects .filter (pk = product_type_id ).first ()
962+ if product_type is None :
963+ return
964+ kwargs ["product_type" ] = product_type
965+
966+ if finding_id is not None :
967+ finding = Finding .objects .filter (pk = finding_id ).select_related ("test__engagement__product" ).first ()
968+ if finding is None :
969+ return
970+ kwargs ["finding" ] = finding
971+
972+ create_notification (event = event , ** kwargs )
973+
974+
914975@app .task (ignore_result = True )
915976def webhook_reactivation (endpoint_id : int , ** _kwargs : dict ) -> None :
916977 get_manager_class_instance ()._get_manager_instance ("webhooks" )._webhook_reactivation (endpoint_id = endpoint_id )
0 commit comments