fix(alerts): thread events now trigger entity-scoped notification alerts#28122
Conversation
Thread change events (THREAD_CREATED, THREAD_UPDATED, POST_CREATED) were
silently dropped by shouldTriggerAlert() when the subscription resource was an
entity type such as 'glossaryTerm' or 'table'.
Root cause: thread ChangeEvents always have entityType='THREAD' (a constant),
not the type of the entity the thread belongs to. The fallback check
config.getResources().contains(event.getEntityType())
evaluated ['glossaryTerm'].contains('THREAD') == false, filtering the event
out before the matchAnyEventType rule could run. Entity Change events worked
because their entityType matched the resource directly.
Fix: extract shouldTriggerAlertForThread(). For thread-type resources
('conversation', 'task', 'announcement') the existing semantics are preserved.
For any other resource the method now checks the thread's parent entity type
via thread.getEntityRef().getType(), so a 'glossaryTerm' alert correctly
fires when a conversation is created or updated on a GlossaryTerm.
Code Review ✅ ApprovedEnables entity-scoped notification alerts for thread events by updating OptionsDisplay: compact → Showing less information. Comment with these commands to change:
Was this helpful? React with 👍 / 👎 | Gitar |
There was a problem hiding this comment.
Pull request overview
This PR fixes notification alert resource filtering so thread events on entity-scoped resources (for example, conversations on glossary terms or tables) are no longer dropped before event rules are evaluated.
Changes:
- Routes
THREADchange events through a dedicated helper. - Preserves conversation/task/announcement resource matching by thread type.
- Adds unit coverage for entity events, thread-type resources, and entity-scoped thread events.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
openmetadata-service/src/main/java/org/openmetadata/service/events/subscription/AlertUtil.java |
Adds thread-specific resource matching against either thread type or parent entity reference type. |
openmetadata-service/src/test/java/org/openmetadata/service/events/subscription/AlertUtilTest.java |
Adds tests covering alert triggering for null/all configs, entity events, thread resources, and entity-scoped thread events. |
|
🟡 Playwright Results — all passed (15 flaky)✅ 4055 passed · ❌ 0 failed · 🟡 15 flaky · ⏭️ 103 skipped
🟡 15 flaky test(s) (passed on retry)
How to debug locally# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip # view trace |
|
Changes have been cherry-picked to the 1.13 branch. |
…rts (#28122) Thread change events (THREAD_CREATED, THREAD_UPDATED, POST_CREATED) were silently dropped by shouldTriggerAlert() when the subscription resource was an entity type such as 'glossaryTerm' or 'table'. Root cause: thread ChangeEvents always have entityType='THREAD' (a constant), not the type of the entity the thread belongs to. The fallback check config.getResources().contains(event.getEntityType()) evaluated ['glossaryTerm'].contains('THREAD') == false, filtering the event out before the matchAnyEventType rule could run. Entity Change events worked because their entityType matched the resource directly. Fix: extract shouldTriggerAlertForThread(). For thread-type resources ('conversation', 'task', 'announcement') the existing semantics are preserved. For any other resource the method now checks the thread's parent entity type via thread.getEntityRef().getType(), so a 'glossaryTerm' alert correctly fires when a conversation is created or updated on a GlossaryTerm. (cherry picked from commit 65dd09b)
|
Changes have been cherry-picked to the 1.12.9 branch. |
…rts (#28122) Thread change events (THREAD_CREATED, THREAD_UPDATED, POST_CREATED) were silently dropped by shouldTriggerAlert() when the subscription resource was an entity type such as 'glossaryTerm' or 'table'. Root cause: thread ChangeEvents always have entityType='THREAD' (a constant), not the type of the entity the thread belongs to. The fallback check config.getResources().contains(event.getEntityType()) evaluated ['glossaryTerm'].contains('THREAD') == false, filtering the event out before the matchAnyEventType rule could run. Entity Change events worked because their entityType matched the resource directly. Fix: extract shouldTriggerAlertForThread(). For thread-type resources ('conversation', 'task', 'announcement') the existing semantics are preserved. For any other resource the method now checks the thread's parent entity type via thread.getEntityRef().getType(), so a 'glossaryTerm' alert correctly fires when a conversation is created or updated on a GlossaryTerm. (cherry picked from commit 65dd09b)
… 1.12.9) Cherry-pick of #28122 referenced EventType.TASK_CREATED, which was added to changeEventType.json on main but is not present on the 1.12.9 schema. Switch to TASK_RESOLVED (a task event that exists in this branch) so the test compiles. The production logic only inspects thread.getType(), not the event type, so test intent is preserved.
… 1.13) Cherry-pick of #28122 referenced EventType.TASK_CREATED, which was added to changeEventType.json on main but is not present on the 1.13 schema. Switch to TASK_RESOLVED (a task event that exists in this branch) so the test compiles. The production logic only inspects thread.getType(), not the event type, so test intent is preserved.



Related to #27889 (partial fix — see Scope below)
Problem
Users configured Notification Alerts for entity types (e.g. GlossaryTerm) and selected Thread Creation / Thread Update event types expecting email notifications when conversations were posted on their glossary terms. No events appeared in the Recent Events tab and no emails were sent. Alerts for Entity Change on the same subscription worked correctly.
Root Cause Analysis
How thread change events are produced
When a thread is created (
POST /api/v1/feed),FeedResourcesets a custom header:ChangeEventHandlerintercepts the response and callsFormatterUtil.createChangeEventForThread(), which produces aChangeEventwith:The event is stored in
change_eventtable — so the events are persisted correctly.Where the events were dropped
AbstractEventConsumer.publishEvents()callsAlertUtil.getFilteredEvents()→checkIfChangeEventIsAllowed()→shouldTriggerAlert().Before the fix,
shouldTriggerAlert()had two paths for thread events:When a user creates a GlossaryTerm alert:
config.getResources()=["glossaryTerm"]"glossaryTerm".equals("announcement" | "task" | "conversation")→ false — skipped["glossaryTerm"].contains("THREAD")→ false — event droppedThe thread event is filtered out before
evaluateAlertConditions()even runs, so thematchAnyEventType("threadCreated", "threadUpdated")rule never gets a chance to evaluate.Why Entity Change events worked
Entity change events on a GlossaryTerm carry
entityType = "glossaryTerm"(the actual entity type), not a constant. Path 2 correctly evaluates:Thread-type resources ("conversation" / "task" / "announcement") also worked
If a user created an alert with resource =
"conversation", Path 1 matched and the thread'sThreadTypewas compared against the resource. This path was correct and is preserved by the fix.Fix
Extracted
shouldTriggerAlertForThread()to consolidate both thread-matching cases:The two dispatch cases are now explicit:
conversation,task,announcementthread.getType().value()(unchanged)glossaryTerm,table,dashboard, …thread.getEntityRef().getType()(new)Files Changed
openmetadata-service/.../events/subscription/AlertUtil.javashouldTriggerAlertForThread()helperopenmetadata-service/.../events/subscription/AlertUtilTest.javaTests
14 new unit tests added to
AlertUtilTest— covering every branch of the fixed logic:shouldTriggerAlert_nullConfig_returnsTrueshouldTriggerAlert_allResource_returnsTrue"all"resource always passesshouldTriggerAlert_entityEvent_matchingResource_returnsTrueshouldTriggerAlert_entityEvent_nonMatchingResource_returnsFalseshouldTriggerAlert_conversationThread_conversationResource_returnsTrueshouldTriggerAlert_taskThread_conversationResource_returnsFalseshouldTriggerAlert_taskThread_taskResource_returnsTrueshouldTriggerAlert_announcementThread_announcementResource_returnsTrueshouldTriggerAlert_conversationOnGlossaryTerm_glossaryTermResource_returnsTrueshouldTriggerAlert_threadUpdateOnGlossaryTerm_glossaryTermResource_returnsTrueshouldTriggerAlert_postCreatedOnGlossaryTerm_glossaryTermResource_returnsTrueshouldTriggerAlert_threadOnTable_glossaryTermResource_returnsFalseshouldTriggerAlert_threadOnTable_tableResource_returnsTrueshouldTriggerAlert_threadWithNullEntityRef_entityTypeResource_returnsFalseAll 23 tests in
AlertUtilTestpass (Tests run: 23, Failures: 0, Errors: 0).How to Reproduce (before fix)
filterByEventTypewiththreadCreated/threadUpdatedentityUpdated→ works immediatelyScope
Fixes the customer-reported reproduction in #27889: resource
glossaryTerm+ filterthreadCreated/threadUpdated/postCreated.Does not fix (still open after this merges):
TaskResource.resolveTask/closeTaskemit no change events.taskCreated/taskUpdatedEventTypevalues are never emitted by any code.AlertsUtil.tsxoffers everyEventTyperegardless of selected resource.