oscerd commented on code in PR #27714:
URL: https://github.com/apache/camel/pull/27714#discussion_r4246979766


##########
core/camel-support/src/main/java/org/apache/camel/support/EventHelper.java:
##########
@@ -1574,6 +1576,49 @@ public static boolean 
notifyExchangeAsyncProcessingStartedEvent(CamelContext con
         return answer;
     }
 
+    /**
+     * Notifies an {@link AiEvent} to the started event notifiers, following 
the same path as every other event
+     * category: it loops the started notifiers, skips those that are disabled 
or have {@code ignoreAiEvents} set,
+     * creates the event lazily (via {@code eventSupplier}) only when some 
notifier wants it, and delivers through
+     * {@code doNotifyEvent} so one failing notifier does not stop delivery to 
the others.
+     * <p>
+     * AI events are their own category: {@code ignoreExchangeEvents} does 
<em>not</em> suppress them even though an
+     * {@code AiEvent} is an exchange event. A notifier opts out with {@code 
setIgnoreAiEvents(true)}.
+     *
+     * @since 4.24
+     */
+    public static boolean notifyAiEvent(CamelContext context, 
Supplier<AiEvent> eventSupplier) {
+        ManagementStrategy management = context != null ? 
context.getManagementStrategy() : null;
+        if (management == null) {
+            return false;
+        }
+
+        List<EventNotifier> notifiers = management.getStartedEventNotifiers();
+        if (notifiers == null || notifiers.isEmpty()) {
+            return false;
+        }
+
+        boolean answer = false;
+        CamelEvent event = null;
+        // optimise for loop using index access to avoid creating iterator 
object
+        for (int i = 0; i < notifiers.size(); i++) {
+            EventNotifier notifier = notifiers.get(i);
+            if (notifier.isDisabled() || notifier.isIgnoreAiEvents()) {

Review Comment:
   Done in 5287ecd38ebb — `notifyAiEvent` now wraps the whole per-notifier body 
(including the `isDisabled()` / `isIgnoreAiEvents()` eligibility checks) in a 
`try/catch(Throwable)` that logs and skips just that notifier, so a broken 
eligibility callback neither escapes (the `AuthorizationDenied` refusal is 
preserved) nor stops delivery to later notifiers — per-notifier, not an outer 
catch.
   
   Note on the test: a notifier throwing from `isDisabled()` also breaks the 
generic lifecycle paths (e.g. context stop's `notifyCamelContextStopping`, 
which calls `isDisabled()` unguarded — a pre-existing pattern across all 
`EventHelper.notifyXxx`, out of this PR's scope). So the test exercises the AI 
eligibility guard via `isIgnoreAiEvents()` (only `notifyAiEvent` calls it) plus 
`isEnabled()`/`notify()` throwing.
   
   _Claude Code on behalf of oscerd_



##########
components/camel-ai/camel-ai-tool/src/test/java/org/apache/camel/component/ai/tool/AiToolAuthorizationDeniedEventTest.java:
##########
@@ -199,6 +231,75 @@ public void notify(CamelEvent event) {
         AiToolResult result = AiToolExecutor.execute(spec, Map.of(), exchange);
 
         
assertThat(result).isInstanceOf(AiToolResult.AuthorizationDenied.class);
+        // the healthy @BeforeEach notifier still received the event despite 
the other one throwing
+        assertThat(events).hasSize(1);

Review Comment:
   Fixed in 5287ecd38ebb — a fresh healthy subscriber is now registered AFTER 
the failing notifiers and the test asserts THAT subscriber's own collection 
received the event, so it would fail if delivery aborted at the failing 
notifier. It covers `isIgnoreAiEvents()`, `isEnabled()` and `notify()` throwing 
(AI-scoped so teardown is unaffected), and keeps the `AuthorizationDenied` 
assertion.
   
   _Claude Code on behalf of oscerd_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to