You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

workflow_run_service.py 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. import threading
  2. from typing import Optional
  3. import contexts
  4. from core.repositories import SQLAlchemyWorkflowNodeExecutionRepository
  5. from core.workflow.repository.workflow_node_execution_repository import OrderConfig
  6. from extensions.ext_database import db
  7. from libs.infinite_scroll_pagination import InfiniteScrollPagination
  8. from models.enums import WorkflowRunTriggeredFrom
  9. from models.model import App
  10. from models.workflow import (
  11. WorkflowNodeExecution,
  12. WorkflowRun,
  13. )
  14. class WorkflowRunService:
  15. def get_paginate_advanced_chat_workflow_runs(self, app_model: App, args: dict) -> InfiniteScrollPagination:
  16. """
  17. Get advanced chat app workflow run list
  18. Only return triggered_from == advanced_chat
  19. :param app_model: app model
  20. :param args: request args
  21. """
  22. class WorkflowWithMessage:
  23. message_id: str
  24. conversation_id: str
  25. def __init__(self, workflow_run: WorkflowRun):
  26. self._workflow_run = workflow_run
  27. def __getattr__(self, item):
  28. return getattr(self._workflow_run, item)
  29. pagination = self.get_paginate_workflow_runs(app_model, args)
  30. with_message_workflow_runs = []
  31. for workflow_run in pagination.data:
  32. message = workflow_run.message
  33. with_message_workflow_run = WorkflowWithMessage(workflow_run=workflow_run)
  34. if message:
  35. with_message_workflow_run.message_id = message.id
  36. with_message_workflow_run.conversation_id = message.conversation_id
  37. with_message_workflow_runs.append(with_message_workflow_run)
  38. pagination.data = with_message_workflow_runs
  39. return pagination
  40. def get_paginate_workflow_runs(self, app_model: App, args: dict) -> InfiniteScrollPagination:
  41. """
  42. Get debug workflow run list
  43. Only return triggered_from == debugging
  44. :param app_model: app model
  45. :param args: request args
  46. """
  47. limit = int(args.get("limit", 20))
  48. base_query = db.session.query(WorkflowRun).filter(
  49. WorkflowRun.tenant_id == app_model.tenant_id,
  50. WorkflowRun.app_id == app_model.id,
  51. WorkflowRun.triggered_from == WorkflowRunTriggeredFrom.DEBUGGING.value,
  52. )
  53. if args.get("last_id"):
  54. last_workflow_run = base_query.filter(
  55. WorkflowRun.id == args.get("last_id"),
  56. ).first()
  57. if not last_workflow_run:
  58. raise ValueError("Last workflow run not exists")
  59. workflow_runs = (
  60. base_query.filter(
  61. WorkflowRun.created_at < last_workflow_run.created_at, WorkflowRun.id != last_workflow_run.id
  62. )
  63. .order_by(WorkflowRun.created_at.desc())
  64. .limit(limit)
  65. .all()
  66. )
  67. else:
  68. workflow_runs = base_query.order_by(WorkflowRun.created_at.desc()).limit(limit).all()
  69. has_more = False
  70. if len(workflow_runs) == limit:
  71. current_page_first_workflow_run = workflow_runs[-1]
  72. rest_count = base_query.filter(
  73. WorkflowRun.created_at < current_page_first_workflow_run.created_at,
  74. WorkflowRun.id != current_page_first_workflow_run.id,
  75. ).count()
  76. if rest_count > 0:
  77. has_more = True
  78. return InfiniteScrollPagination(data=workflow_runs, limit=limit, has_more=has_more)
  79. def get_workflow_run(self, app_model: App, run_id: str) -> Optional[WorkflowRun]:
  80. """
  81. Get workflow run detail
  82. :param app_model: app model
  83. :param run_id: workflow run id
  84. """
  85. workflow_run = (
  86. db.session.query(WorkflowRun)
  87. .filter(
  88. WorkflowRun.tenant_id == app_model.tenant_id,
  89. WorkflowRun.app_id == app_model.id,
  90. WorkflowRun.id == run_id,
  91. )
  92. .first()
  93. )
  94. return workflow_run
  95. def get_workflow_run_node_executions(self, app_model: App, run_id: str) -> list[WorkflowNodeExecution]:
  96. """
  97. Get workflow run node execution list
  98. """
  99. workflow_run = self.get_workflow_run(app_model, run_id)
  100. contexts.plugin_tool_providers.set({})
  101. contexts.plugin_tool_providers_lock.set(threading.Lock())
  102. if not workflow_run:
  103. return []
  104. # Use the repository to get the node executions
  105. repository = SQLAlchemyWorkflowNodeExecutionRepository(
  106. session_factory=db.engine, tenant_id=app_model.tenant_id, app_id=app_model.id
  107. )
  108. # Use the repository to get the node executions with ordering
  109. order_config = OrderConfig(order_by=["index"], order_direction="desc")
  110. node_executions = repository.get_by_workflow_run(workflow_run_id=run_id, order_config=order_config)
  111. return list(node_executions)