Merge remote-tracking branch 'origin/main' into feat/trigger

This commit is contained in:
yessenia
2025-09-25 17:14:24 +08:00
3013 changed files with 148826 additions and 44294 deletions

View File

@ -11,7 +11,7 @@ tenant_id, app_id, triggered_from, etc., which are not part of the core domain m
from collections.abc import Sequence
from datetime import datetime
from typing import Optional, Protocol
from typing import Protocol
from core.workflow.repositories.workflow_node_execution_repository import WorkflowNodeExecutionRepository
from models.workflow import WorkflowNodeExecutionModel
@ -44,7 +44,7 @@ class DifyAPIWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository, Pr
app_id: str,
workflow_id: str,
node_id: str,
) -> Optional[WorkflowNodeExecutionModel]:
) -> WorkflowNodeExecutionModel | None:
"""
Get the most recent execution for a specific node.
@ -87,8 +87,8 @@ class DifyAPIWorkflowNodeExecutionRepository(WorkflowNodeExecutionRepository, Pr
def get_execution_by_id(
self,
execution_id: str,
tenant_id: Optional[str] = None,
) -> Optional[WorkflowNodeExecutionModel]:
tenant_id: str | None = None,
) -> WorkflowNodeExecutionModel | None:
"""
Get a workflow node execution by its ID.

View File

@ -36,7 +36,7 @@ Example:
from collections.abc import Sequence
from datetime import datetime
from typing import Optional, Protocol
from typing import Protocol
from core.workflow.repositories.workflow_execution_repository import WorkflowExecutionRepository
from libs.infinite_scroll_pagination import InfiniteScrollPagination
@ -58,7 +58,7 @@ class APIWorkflowRunRepository(WorkflowExecutionRepository, Protocol):
app_id: str,
triggered_from: str,
limit: int = 20,
last_id: Optional[str] = None,
last_id: str | None = None,
) -> InfiniteScrollPagination:
"""
Get paginated workflow runs with filtering.
@ -90,7 +90,7 @@ class APIWorkflowRunRepository(WorkflowExecutionRepository, Protocol):
tenant_id: str,
app_id: str,
run_id: str,
) -> Optional[WorkflowRun]:
) -> WorkflowRun | None:
"""
Get a specific workflow run by ID.

View File

@ -7,9 +7,8 @@ using SQLAlchemy 2.0 style queries for WorkflowNodeExecutionModel operations.
from collections.abc import Sequence
from datetime import datetime
from typing import Optional
from sqlalchemy import delete, desc, select
from sqlalchemy import asc, delete, desc, select
from sqlalchemy.orm import Session, sessionmaker
from models.workflow import WorkflowNodeExecutionModel
@ -49,7 +48,7 @@ class DifyAPISQLAlchemyWorkflowNodeExecutionRepository(DifyAPIWorkflowNodeExecut
app_id: str,
workflow_id: str,
node_id: str,
) -> Optional[WorkflowNodeExecutionModel]:
) -> WorkflowNodeExecutionModel | None:
"""
Get the most recent execution for a specific node.
@ -63,11 +62,14 @@ class DifyAPISQLAlchemyWorkflowNodeExecutionRepository(DifyAPIWorkflowNodeExecut
node_id: The node identifier
Returns:
The most recent WorkflowNodeExecutionModel for the node, or None if not found
The most recent WorkflowNodeExecutionModel for the node, or None if not found.
The returned WorkflowNodeExecutionModel will have `offload_data` preloaded.
"""
stmt = select(WorkflowNodeExecutionModel)
stmt = WorkflowNodeExecutionModel.preload_offload_data(stmt)
stmt = (
select(WorkflowNodeExecutionModel)
.where(
stmt.where(
WorkflowNodeExecutionModel.tenant_id == tenant_id,
WorkflowNodeExecutionModel.app_id == app_id,
WorkflowNodeExecutionModel.workflow_id == workflow_id,
@ -100,15 +102,12 @@ class DifyAPISQLAlchemyWorkflowNodeExecutionRepository(DifyAPIWorkflowNodeExecut
Returns:
A sequence of WorkflowNodeExecutionModel instances ordered by index (desc)
"""
stmt = (
select(WorkflowNodeExecutionModel)
.where(
WorkflowNodeExecutionModel.tenant_id == tenant_id,
WorkflowNodeExecutionModel.app_id == app_id,
WorkflowNodeExecutionModel.workflow_run_id == workflow_run_id,
)
.order_by(desc(WorkflowNodeExecutionModel.index))
)
stmt = WorkflowNodeExecutionModel.preload_offload_data(select(WorkflowNodeExecutionModel))
stmt = stmt.where(
WorkflowNodeExecutionModel.tenant_id == tenant_id,
WorkflowNodeExecutionModel.app_id == app_id,
WorkflowNodeExecutionModel.workflow_run_id == workflow_run_id,
).order_by(asc(WorkflowNodeExecutionModel.created_at))
with self._session_maker() as session:
return session.execute(stmt).scalars().all()
@ -116,8 +115,8 @@ class DifyAPISQLAlchemyWorkflowNodeExecutionRepository(DifyAPIWorkflowNodeExecut
def get_execution_by_id(
self,
execution_id: str,
tenant_id: Optional[str] = None,
) -> Optional[WorkflowNodeExecutionModel]:
tenant_id: str | None = None,
) -> WorkflowNodeExecutionModel | None:
"""
Get a workflow node execution by its ID.
@ -135,7 +134,8 @@ class DifyAPISQLAlchemyWorkflowNodeExecutionRepository(DifyAPIWorkflowNodeExecut
Returns:
The WorkflowNodeExecutionModel if found, or None if not found
"""
stmt = select(WorkflowNodeExecutionModel).where(WorkflowNodeExecutionModel.id == execution_id)
stmt = WorkflowNodeExecutionModel.preload_offload_data(select(WorkflowNodeExecutionModel))
stmt = stmt.where(WorkflowNodeExecutionModel.id == execution_id)
# Add tenant filtering if provided
if tenant_id is not None:

View File

@ -22,7 +22,6 @@ Implementation Notes:
import logging
from collections.abc import Sequence
from datetime import datetime
from typing import Optional, cast
from sqlalchemy import delete, select
from sqlalchemy.orm import Session, sessionmaker
@ -46,7 +45,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
session_maker: SQLAlchemy sessionmaker instance for database connections
"""
def __init__(self, session_maker: sessionmaker[Session]) -> None:
def __init__(self, session_maker: sessionmaker[Session]):
"""
Initialize the repository with a sessionmaker.
@ -61,7 +60,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
app_id: str,
triggered_from: str,
limit: int = 20,
last_id: Optional[str] = None,
last_id: str | None = None,
) -> InfiniteScrollPagination:
"""
Get paginated workflow runs with filtering.
@ -107,7 +106,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
tenant_id: str,
app_id: str,
run_id: str,
) -> Optional[WorkflowRun]:
) -> WorkflowRun | None:
"""
Get a specific workflow run by ID with tenant and app isolation.
"""
@ -117,7 +116,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
WorkflowRun.app_id == app_id,
WorkflowRun.id == run_id,
)
return cast(Optional[WorkflowRun], session.scalar(stmt))
return session.scalar(stmt)
def get_expired_runs_batch(
self,
@ -137,7 +136,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
)
.limit(batch_size)
)
return cast(Sequence[WorkflowRun], session.scalars(stmt).all())
return session.scalars(stmt).all()
def delete_runs_by_ids(
self,
@ -154,7 +153,7 @@ class DifyAPISQLAlchemyWorkflowRunRepository(APIWorkflowRunRepository):
result = session.execute(stmt)
session.commit()
deleted_count = cast(int, result.rowcount)
deleted_count = result.rowcount
logger.info("Deleted %s workflow runs by IDs", deleted_count)
return deleted_count