Skip to content

refactor(api): inject app trigger publication and quota status lifecycle - #45188

Open
hjlarry wants to merge 3 commits into
hjlarry/trigger-workflow-bindingsfrom
hjlarry/trigger-app-lifecycle
Open

hjlarry wants to merge 3 commits into
hjlarry/trigger-workflow-bindingsfrom
hjlarry/trigger-app-lifecycle

Conversation

@hjlarry

@hjlarry hjlarry commented Oct 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Part of #39993. Stacked on #45172; merge that PR first.

Move App Trigger registration and quota status updates into injected services backed by the shared app trigger repository. Workflow publication now registers, updates and removes triggers in the caller's transaction, so registration rolls back with the published graph. Preserve existing trigger IDs, enablement and provider/type metadata, update nonempty titles, and enable newly registered nodes.

Webhook, plugin-event and scheduled execution receive the same quota status service. It marks only enabled triggers in the affected tenant as rate limited; persistence failures remain logged and do not replace the original quota rejection. Keep SQL in the repository and retain the borrowed publication Session until publication exposes an injected unit of work.

Add real SQLite coverage for publication commit/rollback, tenant/app isolation, metadata preservation and quota-write failures, and extend the PostgreSQL publication test to assert App Trigger rollback. Existing webhook and task callers are adapted to the injected service; their broader runtime migration remains in later layers.

Stack prerequisite

This layer also depends on #44457, which is already merged into main. The current stack base predates that change, so this branch retains its prerequisite merge and GitHub's aggregate diff includes those earlier changes. The new lifecycle changes are isolated in commit 2cabe6c35e. Refreshing the lower stack onto main will remove the prerequisite changes from this PR's diff.

Screenshots

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've verified the change and added or updated tests where meaningful regression risk justifies coverage.
  • I've updated the documentation accordingly.
  • I ran make lint && make type-check (backend) and vp staged (frontend) to appease the lint gods

@hjlarry
hjlarry added this pull request to stack #44506 October 31, 2026 02:54
@github-actions github-actions Bot added web This relates to changes on the web. size:XXL This PR changes 1000+ lines, ignoring generated files. labels Oct 31, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Pyrefly Type Coverage

Metric Base PR Delta
Type coverage 76.86% 76.91% +0.05%
Strict coverage 76.54% 76.59% +0.05%
Typed symbols 66,089 66,243 +154
Untyped symbols 19,982 19,971 -11
Modules 3898 3902 +4

@github-actions

Copy link
Copy Markdown
Contributor

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-10-31 02:55:16.384997724 +0000
+++ /tmp/pyrefly_pr.txt	2026-10-31 02:55:06.700911801 +0000
@@ -743,9 +743,9 @@
 ERROR Argument `Literal['account']` is not assignable to parameter `created_by_role` with type `CreatorUserRole | SQLCoreOperations[CreatorUserRole]` in function `models.web.PinnedConversation.__init__` [bad-argument-type]
    --> tests/test_containers_integration_tests/services/test_web_conversation_service.py:270:29
 ERROR Argument `Literal['normal']` is not assignable to parameter `status` with type `SQLCoreOperations[TenantStatus] | TenantStatus` in function `models.account.Tenant.__init__` [bad-argument-type]
-  --> tests/test_containers_integration_tests/services/test_webhook_service_relationships.py:67:72
+  --> tests/test_containers_integration_tests/services/test_webhook_service_relationships.py:68:72
 ERROR Class `WebhookServiceRelationshipFactory` has no class attribute `_read_cache` [missing-attribute]
-   --> tests/test_containers_integration_tests/services/test_webhook_service_relationships.py:543:26
+   --> tests/test_containers_integration_tests/services/test_webhook_service_relationships.py:546:26
 ERROR Object of class `NoneType` has no attribute `id` [missing-attribute]
    --> tests/test_containers_integration_tests/services/test_workflow_app_service.py:125:38
 ERROR Object of class `NoneType` has no attribute `status` [missing-attribute]
@@ -1245,11 +1245,9 @@
 ERROR Object of class `int` has no attribute `lower` [missing-attribute]
    --> tests/unit_tests/controllers/console/app/test_annotation_security.py:293:35
 ERROR Object of class `FromClause` has no attribute `create` [missing-attribute]
-   --> tests/unit_tests/controllers/console/app/test_app_apis.py:132:9
-ERROR Object of class `FromClause` has no attribute `create` [missing-attribute]
-   --> tests/unit_tests/controllers/console/app/test_app_apis.py:133:9
+   --> tests/unit_tests/controllers/console/app/test_app_apis.py:127:9
 ERROR Argument value `Literal[0]` violates Pydantic `ge` constraint `Literal[1]` for field `page` [bad-argument-type]
-   --> tests/unit_tests/controllers/console/app/test_app_apis.py:838:51
+   --> tests/unit_tests/controllers/console/app/test_app_apis.py:799:51
 ERROR Object of class `App` has no attribute `create_user_name` [missing-attribute]
    --> tests/unit_tests/controllers/console/app/test_app_response_models.py:112:5
 ERROR Object of class `App` has no attribute `permission_keys` [missing-attribute]
@@ -1607,7 +1605,7 @@
 ERROR Object of class `FromClause` has no attribute `drop` [missing-attribute]
   --> tests/unit_tests/controllers/trigger/test_trigger.py:46:5
 ERROR `_RequestStub` is not assignable to attribute `request` with type `Request` [bad-assignment]
-  --> tests/unit_tests/controllers/trigger/test_webhook.py:32:22
+  --> tests/unit_tests/controllers/trigger/test_webhook.py:41:22
 ERROR Object of class `Exception` has no attribute `data` [missing-attribute]
    --> tests/unit_tests/controllers/web/test_app.py:250:16
 ERROR Object of class `ModuleType` has no attribute `web_ns` [missing-attribute]
@@ -5065,33 +5063,33 @@
 ERROR Argument `list[File]` is not assignable to parameter `value` with type `list[object]` in function `services.variable_truncator.VariableTruncator._truncate_array` [bad-argument-type]
    --> tests/unit_tests/services/test_variable_truncator.py:751:44
 ERROR Argument `dict[str, dict[Unknown, Unknown]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:504:79
+   --> tests/unit_tests/services/test_webhook_service.py:516:79
 ERROR Argument `dict[str, dict[str, int | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:514:79
+   --> tests/unit_tests/services/test_webhook_service.py:526:79
 ERROR Argument `dict[str, dict[str, int | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:524:79
+   --> tests/unit_tests/services/test_webhook_service.py:536:79
 ERROR Argument `dict[str, dict[str, int | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:533:79
+   --> tests/unit_tests/services/test_webhook_service.py:545:79
 ERROR Argument `dict[str, dict[str, int | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:542:79
+   --> tests/unit_tests/services/test_webhook_service.py:554:79
 ERROR Argument `dict[str, dict[str, int | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.generate_webhook_response` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:552:79
+   --> tests/unit_tests/services/test_webhook_service.py:564:79
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:794:88
+   --> tests/unit_tests/services/test_webhook_service.py:806:88
 ERROR Argument `dict[str, dict[str, str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:821:83
+   --> tests/unit_tests/services/test_webhook_service.py:833:83
 ERROR Argument `dict[str, dict[str, str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:841:83
+   --> tests/unit_tests/services/test_webhook_service.py:853:83
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:859:86
+   --> tests/unit_tests/services/test_webhook_service.py:871:86
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:878:91
+   --> tests/unit_tests/services/test_webhook_service.py:890:91
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:900:86
+   --> tests/unit_tests/services/test_webhook_service.py:912:86
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:919:86
+   --> tests/unit_tests/services/test_webhook_service.py:931:86
 ERROR Argument `dict[str, dict[str, list[dict[str, bool | str]] | str]]` is not assignable to parameter `node_config` with type `NodeConfigDict` in function `services.trigger.webhook_service.WebhookService.extract_and_validate_webhook_data` [bad-argument-type]
-   --> tests/unit_tests/services/test_webhook_service.py:937:91
+   --> tests/unit_tests/services/test_webhook_service.py:949:91
 ERROR Argument `dict[str, str | dict[str, str]]` is not assignable to parameter `webhook_data` with type `RawWebhookDataDict` in function `services.trigger.webhook_service.WebhookService._validate_http_metadata` [bad-argument-type]
    --> tests/unit_tests/services/test_webhook_service_additional.py:249:57
 ERROR Argument `dict[str, dict[str, int] | dict[str, str]]` is not assignable to parameter `webhook_data` with type `RawWebhookDataDict` in function `services.trigger.webhook_service.WebhookService.build_workflow_inputs` [bad-argument-type]

@codecov

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.41270% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 88.12%. Comparing base (730ccc7) to head (2cabe6c).

Files with missing lines Patch % Lines
api/tasks/workflow_schedule_tasks.py 0.00% 2 Missing ⚠️
api/services/trigger/webhook_service.py 0.00% 1 Missing ⚠️
Additional details and impacted files
@@                          Coverage Diff                          @@
##           hjlarry/trigger-workflow-bindings   #45188      +/-   ##
=====================================================================
+ Coverage                              88.10%   88.12%   +0.01%     
=====================================================================
  Files                                   5584     5586       +2     
  Lines                                 334112   334184      +72     
  Branches                               66807    66805       -2     
=====================================================================
+ Hits                                  294384   294491     +107     
+ Misses                                 34504    34474      -30     
+ Partials                                5224     5219       -5     
Flag Coverage Δ
api 87.65% <98.41%> (+0.03%) ⬆️
cli 94.27% <ø> (ø)
dify-ui 91.67% <ø> (ø)
web 88.53% <ø> (-0.01%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant