feat(trigger): update plugin trigger API and model to use trigger_name

- Modified `PluginTriggerApi` to accept `trigger_name` as a JSON argument and return encoded plugin triggers.
- Updated `WorkflowPluginTrigger` model to replace `trigger_id` with `trigger_name` for better clarity.
- Adjusted `WorkflowPluginTriggerService` to handle the new `trigger_name` field and ensure proper error handling for subscriptions.
- Enhanced `workflow_trigger_fields` to include `trigger_name` in the plugin trigger schema.

This change improves the API's clarity and aligns the model with the updated naming conventions.
This commit is contained in:
Harry 2025-09-05 15:55:19 +08:00
parent 85caa5bd0c
commit 814787677a
5 changed files with 67 additions and 39 deletions

View File

@ -10,6 +10,7 @@ from configs import dify_config
from controllers.console import api
from controllers.console.app.wraps import get_app_model
from controllers.console.wraps import account_initialization_required, setup_required
from core.model_runtime.utils.encoders import jsonable_encoder
from extensions.ext_database import db
from fields.workflow_trigger_fields import trigger_fields, triggers_list_fields, webhook_trigger_fields
from libs.login import current_user, login_required
@ -31,10 +32,10 @@ class PluginTriggerApi(Resource):
def post(self, app_model):
"""Create plugin trigger"""
parser = reqparse.RequestParser()
parser.add_argument("node_id", type=str, required=True, help="Node ID is required")
parser.add_argument("provider_id", type=str, required=True, help="Provider ID is required")
parser.add_argument("trigger_name", type=str, required=True, help="Trigger name is required")
parser.add_argument("subscription_id", type=str, required=True, help="Subscription ID is required")
parser.add_argument("node_id", type=str, required=False, location="json")
parser.add_argument("provider_id", type=str, required=False, location="json")
parser.add_argument("trigger_name", type=str, required=False, location="json")
parser.add_argument("subscription_id", type=str, required=False, location="json")
args = parser.parse_args()
assert isinstance(current_user, Account)
@ -51,7 +52,7 @@ class PluginTriggerApi(Resource):
subscription_id=args["subscription_id"],
)
return plugin_trigger
return jsonable_encoder(plugin_trigger)
@setup_required
@login_required
@ -68,7 +69,7 @@ class PluginTriggerApi(Resource):
node_id=args["node_id"],
)
return plugin_trigger
return jsonable_encoder(plugin_trigger)
@setup_required
@login_required
@ -78,9 +79,7 @@ class PluginTriggerApi(Resource):
"""Update plugin trigger"""
parser = reqparse.RequestParser()
parser.add_argument("node_id", type=str, required=True, help="Node ID is required")
parser.add_argument("provider_id", type=str, required=False, help="Provider ID")
parser.add_argument("trigger_name", type=str, required=False, help="Trigger name")
parser.add_argument("subscription_id", type=str, required=False, help="Subscription ID")
parser.add_argument("subscription_id", type=str, required=True, location="json", help="Subscription ID")
args = parser.parse_args()
assert isinstance(current_user, Account)
@ -91,12 +90,10 @@ class PluginTriggerApi(Resource):
plugin_trigger = WorkflowPluginTriggerService.update_plugin_trigger(
app_id=app_model.id,
node_id=args["node_id"],
provider_id=args.get("provider_id"),
trigger_name=args.get("trigger_name"),
subscription_id=args.get("subscription_id"),
subscription_id=args["subscription_id"],
)
return plugin_trigger
return jsonable_encoder(plugin_trigger)
@setup_required
@login_required

View File

@ -0,0 +1,37 @@
"""plugin_trigger_idx
Revision ID: 875c659da2f8
Revises: 86f068bf56fb
Create Date: 2025-09-05 15:51:08.635283
"""
from alembic import op
import models as models
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '875c659da2f8'
down_revision = '86f068bf56fb'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('workflow_plugin_triggers', schema=None) as batch_op:
batch_op.add_column(sa.Column('trigger_name', sa.String(length=255), nullable=False))
batch_op.drop_index(batch_op.f('workflow_plugin_trigger_tenant_subscription_idx'))
batch_op.create_index('workflow_plugin_trigger_tenant_subscription_idx', ['tenant_id', 'subscription_id', 'trigger_name'], unique=False)
batch_op.drop_column('trigger_id')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('workflow_plugin_triggers', schema=None) as batch_op:
batch_op.add_column(sa.Column('trigger_id', sa.VARCHAR(length=255), autoincrement=False, nullable=False))
batch_op.drop_index('workflow_plugin_trigger_tenant_subscription_idx')
batch_op.create_index(batch_op.f('workflow_plugin_trigger_tenant_subscription_idx'), ['tenant_id', 'subscription_id'], unique=False)
batch_op.drop_column('trigger_name')
# ### end Alembic commands ###

View File

@ -1438,7 +1438,7 @@ class WorkflowPluginTrigger(Base):
- node_id (varchar) Node ID which node in the workflow
- tenant_id (uuid) Workspace ID
- provider_id (varchar) Plugin provider ID
- trigger_id (varchar) trigger id (github_issues_trigger)
- trigger_name (varchar) trigger name (github_issues_trigger)
- subscription_id (varchar) Subscription ID
- created_at (timestamp) Creation time
- updated_at (timestamp) Last update time
@ -1447,7 +1447,7 @@ class WorkflowPluginTrigger(Base):
__tablename__ = "workflow_plugin_triggers"
__table_args__ = (
sa.PrimaryKeyConstraint("id", name="workflow_plugin_trigger_pkey"),
sa.Index("workflow_plugin_trigger_tenant_subscription_idx", "tenant_id", "subscription_id", "trigger_id"),
sa.Index("workflow_plugin_trigger_tenant_subscription_idx", "tenant_id", "subscription_id", "trigger_name"),
sa.UniqueConstraint("app_id", "node_id", name="uniq_app_node_subscription"),
)
@ -1456,7 +1456,7 @@ class WorkflowPluginTrigger(Base):
node_id: Mapped[str] = mapped_column(String(64), nullable=False)
tenant_id: Mapped[str] = mapped_column(StringUUID, nullable=False)
provider_id: Mapped[str] = mapped_column(String(512), nullable=False)
trigger_id: Mapped[str] = mapped_column(String(255), nullable=False)
trigger_name: Mapped[str] = mapped_column(String(255), nullable=False)
subscription_id: Mapped[str] = mapped_column(String(255), nullable=False)
created_at: Mapped[datetime] = mapped_column(DateTime, nullable=False, server_default=func.current_timestamp())
updated_at: Mapped[datetime] = mapped_column(

View File

@ -176,7 +176,7 @@ class TriggerService:
select(WorkflowPluginTrigger).where(
WorkflowPluginTrigger.tenant_id == subscription.tenant_id,
WorkflowPluginTrigger.subscription_id == subscription.id,
WorkflowPluginTrigger.trigger_id == trigger.identity.name,
WorkflowPluginTrigger.trigger_name == trigger.identity.name,
)
).all()
return list(subscribers)

View File

@ -2,7 +2,7 @@ from typing import Optional
from sqlalchemy import select
from sqlalchemy.orm import Session
from werkzeug.exceptions import BadRequest, NotFound
from werkzeug.exceptions import NotFound
from extensions.ext_database import db
from models.trigger import TriggerSubscription
@ -38,9 +38,6 @@ class WorkflowPluginTriggerService:
Raises:
BadRequest: If plugin trigger already exists for this app and node
"""
# Create trigger_id from provider_id and trigger_name
trigger_id = f"{provider_id}:{trigger_name}"
with Session(db.engine) as session:
# Check if plugin trigger already exists for this app and node
# Based on unique constraint: uniq_app_node
@ -52,7 +49,7 @@ class WorkflowPluginTriggerService:
)
if existing_trigger:
raise BadRequest("Plugin trigger already exists for this app and node")
raise ValueError("Plugin trigger already exists for this app and node")
# Check if subscription exists
subscription = session.scalar(
@ -62,7 +59,7 @@ class WorkflowPluginTriggerService:
)
if not subscription:
raise BadRequest("Subscription not found")
raise NotFound("Subscription not found")
# Create new plugin trigger
plugin_trigger = WorkflowPluginTrigger(
@ -70,7 +67,7 @@ class WorkflowPluginTriggerService:
node_id=node_id,
tenant_id=tenant_id,
provider_id=provider_id,
trigger_id=trigger_id,
trigger_name=trigger_name,
subscription_id=subscription_id,
)
@ -194,17 +191,13 @@ class WorkflowPluginTriggerService:
cls,
app_id: str,
node_id: str,
provider_id: Optional[str] = None,
trigger_name: Optional[str] = None,
subscription_id: Optional[str] = None,
subscription_id: str,
) -> WorkflowPluginTrigger:
"""Update a plugin trigger
Args:
app_id: The app ID
node_id: The node ID in the workflow
provider_id: The new provider ID (optional)
trigger_name: The new trigger name (optional)
subscription_id: The new subscription ID (optional)
Returns:
@ -225,17 +218,18 @@ class WorkflowPluginTriggerService:
if not plugin_trigger:
raise NotFound("Plugin trigger not found")
# Update fields if provided
if provider_id:
plugin_trigger.provider_id = provider_id
# Check if subscription exists
subscription = session.scalar(
select(TriggerSubscription).where(
TriggerSubscription.id == subscription_id,
)
)
if trigger_name:
# Update trigger_id if provider_id or trigger_name changed
provider_id = provider_id or plugin_trigger.provider_id
plugin_trigger.trigger_id = f"{provider_id}:{trigger_name}"
if not subscription:
raise NotFound("Subscription not found")
if subscription_id:
plugin_trigger.subscription_id = subscription_id
# Update subscription ID
plugin_trigger.subscription_id = subscription_id
session.commit()
session.refresh(plugin_trigger)
@ -285,7 +279,7 @@ class WorkflowPluginTriggerService:
if trigger_name:
# Update trigger_id if provider_id or trigger_name changed
provider_id = provider_id or plugin_trigger.provider_id
plugin_trigger.trigger_id = f"{provider_id}:{trigger_name}"
plugin_trigger.trigger_name = f"{provider_id}:{trigger_name}"
if new_subscription_id:
plugin_trigger.subscription_id = new_subscription_id