Skip to content

fix(triggers): test-event 500, single-click test, dismiss drawer on create#5259

Merged
ardaerzin merged 7 commits into
big-agentsfrom
fe-fixes/agent-triggers
Jul 12, 2026
Merged

fix(triggers): test-event 500, single-click test, dismiss drawer on create#5259
ardaerzin merged 7 commits into
big-agentsfrom
fe-fixes/agent-triggers

Conversation

@ardaerzin

Copy link
Copy Markdown
Contributor

Context

Three trigger issues. Testing an app trigger failed with "an unexpected error occurred" whenever a live subscription already covered the same connection and event. The provider upsert returns the same trigger id, the partial-unique index rejects a second active row, and that database error was flattened to a generic 500. The test UI also took two clicks (open the popover, then "Wait for a new event"). And creating a trigger left the drawer open.

Changes

Backend: the DAO translates the unique-index violation into a typed conflict, so the API returns a clean 409 instead of a 500. test_subscription detects an existing live subscription for the same connection and event and captures against it instead of minting a duplicate. A freshly minted test subscription is still created and torn down as before.

Frontend: the app-trigger test flask starts the wait on a single click (opt-in autoWaitOnOpen on the shared picker; the other pickers keep their two-step flow). Creating a trigger, subscription or schedule, now dismisses the drawer. The triggers list refreshes from the create mutation's own cache invalidation.

Tests / notes

  • Added a pytest for the reuse-on-conflict path; the existing test-mode tests still pass.
  • The DAO change is on the shared create path, but it only changes the error type for an already-failing duplicate create (500 to 409). No operation that used to succeed now fails.

What to QA

  • With a saved live app trigger for some connection and event, start a new draft for the same event and wait for an event. It captures instead of 500ing.
  • Click the "Run in playground" flask on a trigger row once. It starts waiting immediately; recent events are still listed below.
  • Create an app trigger and a schedule. The drawer closes and the new trigger shows in the list. Editing a trigger keeps the drawer open.

@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jul 12, 2026 10:26pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: c35d1f87-1364-4017-b3c4-32838a98ee9e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Backend trigger testing now handles active subscription conflicts by reusing existing subscriptions and filtering deliveries. Frontend trigger controls support automatic event capture and distinguish create versus edit drawer behavior.

Changes

Backend subscription reuse

Layer / File(s) Summary
Subscription conflict translation
api/oss/src/core/triggers/interfaces.py, api/oss/src/dbs/postgres/triggers/dao.py
The DAO exposes live-subscription lookup and translates active-trigger uniqueness violations into EntityCreationConflict, while re-raising unrelated integrity errors.
Test subscription reuse and cleanup
api/oss/src/core/triggers/service.py, api/oss/tests/pytest/unit/triggers/test_triggers_subscription_test_mode.py
Testing reuses conflicting live subscriptions, ignores the baseline delivery, preserves reused subscriptions, and validates the behavior with unit coverage.

Frontend trigger capture

Layer / File(s) Summary
Automatic event capture
web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/EventSourcePicker.tsx, web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/TriggerManagementSection.tsx
The picker can wait for an event when opened and prevents settled interactions from applying late capture results.
Create and edit drawer completion
web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerScheduleDrawer.tsx, web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerSubscriptionDrawer.tsx
Create flows close drawers, while edit flows conditionally invoke saved callbacks or close.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TriggerTest
  participant TriggersService
  participant TriggersDAO
  participant PostgreSQL
  participant DeliveryStore
  TriggerTest->>TriggersService: test subscription
  TriggersService->>TriggersDAO: create subscription
  TriggersDAO->>PostgreSQL: persist active subscription
  PostgreSQL-->>TriggersDAO: uniqueness conflict
  TriggersDAO-->>TriggersService: EntityCreationConflict
  TriggersService->>TriggersDAO: fetch existing subscription
  TriggersService->>DeliveryStore: poll deliveries after baseline
  DeliveryStore-->>TriggersService: newly captured delivery
  TriggersService-->>TriggerTest: return delivery
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main changes: trigger test failure handling, single-click testing, and drawer dismissal on create.
Description check ✅ Passed The description is directly related to the PR and summarizes the backend and frontend trigger fixes accurately.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fe-fixes/agent-triggers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@dosubot dosubot Bot added Bug Report Something isn't working size:L This PR changes 100-499 lines, ignoring generated files. labels Jul 12, 2026
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/EventSourcePicker.tsx (1)

66-78: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Unhandled promise rejection in wait() when onWaitForEvent throws.

wait() has a try/finally with no catch, so if onWaitForEvent() rejects, the error propagates. In handleOpenChange (Line 86), void wait() discards the promise, turning the rejection into an unhandled promise rejection. The button-click path (Line 95, onClick={wait}) has the same issue since React event handlers don't catch async exceptions.

Add a catch block to handle errors gracefully:

🛡️ Proposed fix
     const wait = async () => {
         if (!onWaitForEvent || waiting) return
         setWaiting(true)
         try {
             const event = await onWaitForEvent()
             if (event && !settledRef.current) {
                 settledRef.current = true
                 setOpen(false)
                 onPick(event)
             }
+        } catch {
+            // Swallow — callers of onWaitForEvent are expected to surface
+            // their own error messages (e.g. message.error) before rejecting.
         } finally {
             setWaiting(false)
         }
     }
🧹 Nitpick comments (1)
api/oss/src/core/triggers/service.py (1)

1196-1208: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Use trigger_id from the conflict for a precise, safe lookup.

EntityCreationConflict already carries trigger_id in its conflict dict (DAO line 91). Using get_project_and_subscription_by_trigger_id — which filters by deleted_at.is_(None) — is more precise than the current connection_id + event_key query and avoids the soft-delete risk flagged above.

♻️ Suggested refactor: trigger_id-based reuse lookup
         except EntityCreationConflict as conflict:
-            existing = await self.dao.query_subscriptions(
-                project_id=project_id,
-                subscription=TriggerSubscriptionQuery(
-                    connection_id=subscription.connection_id,
-                    event_key=subscription.data.event_key,
-                ),
-                windowing=Windowing(limit=1),
-            )
-            if not existing:
+            trigger_id = (
+                conflict.conflict.get("trigger_id")
+                if conflict.conflict
+                else None
+            )
+            found = None
+            if trigger_id:
+                result = (
+                    await self.dao.get_project_and_subscription_by_trigger_id(
+                        trigger_id=trigger_id,
+                    )
+                )
+                if result:
+                    found = result[1]
+            if found is None:
                 raise
-            created = existing[0]
+            created = found
             owns_created = False

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 7116b35a-3fbd-476d-ac0c-5a61e42d4a26

📥 Commits

Reviewing files that changed from the base of the PR and between cc07623 and 93be917.

📒 Files selected for processing (7)
  • api/oss/src/core/triggers/service.py
  • api/oss/src/dbs/postgres/triggers/dao.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_subscription_test_mode.py
  • web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/TriggerManagementSection.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerScheduleDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/TriggerSubscriptionDrawer.tsx
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/EventSourcePicker.tsx

Comment thread api/oss/src/core/triggers/service.py Outdated
@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/oss/src/dbs/postgres/triggers/dao.py (1)

75-93: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Classify the uniqueness violation from the underlying constraint metadata. Matching str(e.orig) is brittle here and can let duplicate active subscriptions fall back to a generic 500. Re-raise unrelated IntegrityErrors unchanged.

🧹 Nitpick comments (1)
api/oss/src/dbs/postgres/triggers/dao.py (1)

75-93: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add persistence-level regression coverage for the new contract.

The current service test mocks both DAO methods, so it will not catch incorrect index detection, cross-project matches, or deleted subscriptions being returned. Add tests covering active lookup, deleted/cross-project exclusion, and re-raising unrelated IntegrityError instances.

Also applies to: 234-258


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ddb3a045-fd09-4ea5-a915-faaa3adce272

📥 Commits

Reviewing files that changed from the base of the PR and between 93be917 and 210eee1.

📒 Files selected for processing (5)
  • api/oss/src/core/triggers/interfaces.py
  • api/oss/src/core/triggers/service.py
  • api/oss/src/dbs/postgres/triggers/dao.py
  • api/oss/tests/pytest/unit/triggers/test_triggers_subscription_test_mode.py
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/EventSourcePicker.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • api/oss/tests/pytest/unit/triggers/test_triggers_subscription_test_mode.py
  • web/packages/agenta-entity-ui/src/gatewayTrigger/drawers/shared/EventSourcePicker.tsx
  • api/oss/src/core/triggers/service.py

@ardaerzin

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@ardaerzin ardaerzin merged commit 3b1db8c into big-agents Jul 12, 2026
15 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Report Something isn't working size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant