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]