main
py 183 lines 6.5 KB
Raw
1 import asyncio
2 from typing import List
3
4 from fastapi import HTTPException
5 from loguru import logger
6
7 from app.connectors.shuffle.schema.workflows import ExecuteWorklow
8 from app.connectors.shuffle.schema.workflows import RequestWorkflowExecutionModel
9 from app.connectors.shuffle.schema.workflows import WorkflowExecutionBodyModel
10 from app.connectors.shuffle.schema.workflows import WorkflowExecutionStatusResponseModel
11 from app.connectors.shuffle.schema.workflows import WorkflowsResponse
12 from app.connectors.shuffle.utils.universal import send_get_request
13 from app.connectors.shuffle.utils.universal import send_post_request
14
15
16 def remove_large_images_from_actions(workflows: List) -> List:
17 """
18 Removes the `large_image` keys from actions in each workflow.
19
20 Args:
21 workflows (List): A list of workflows.
22
23 Returns:
24 List: The updated list of workflows with `large_image` keys removed from actions.
25 """
26 for workflow in workflows:
27 if "actions" in workflow:
28 for action in workflow["actions"]:
29 action.pop(
30 "large_image",
31 None,
32 ) # Use pop to avoid KeyError if 'large_image' does not exist
33 return workflows
34
35
36 async def get_workflows() -> WorkflowsResponse:
37 """
38 Returns a list of workflows.
39
40 :return: WorkflowsResponse object containing the list of workflows.
41 :rtype: WorkflowsResponse
42 """
43 logger.info("Getting workflows")
44
45 try:
46 response = await send_get_request("/api/v1/workflows")
47 if response is None:
48 return WorkflowsResponse(
49 success=False,
50 message="Failed to get workflows",
51 workflows=[],
52 )
53
54 workflows = response.get("data")
55 workflows_without_large_images = remove_large_images_from_actions(workflows)
56
57 return WorkflowsResponse(
58 success=True,
59 message="Successfully fetched workflows",
60 workflows=workflows_without_large_images,
61 )
62
63 except Exception as e:
64 logger.error(f"Failed to get workflows with error: {e}")
65 raise HTTPException(
66 status_code=500,
67 detail=f"Failed to get workflows with error: {e}",
68 )
69
70
71 async def get_workflow_executions(
72 exection_body: WorkflowExecutionBodyModel,
73 ) -> WorkflowExecutionStatusResponseModel:
74 """
75 Returns a list of workflow executions.
76
77 Parameters:
78 - exection_body (WorkflowExecutionBodyModel): The body of the workflow execution request.
79
80 Returns:
81 - WorkflowExecutionStatusResponseModel: The response model containing the status of the last run.
82
83 Raises:
84 - HTTPException: If there is an error while getting the workflow executions.
85 """
86 logger.info("Getting workflow executions")
87 response = await send_get_request(
88 f"/api/v1/workflows/{exection_body.workflow_id}/executions",
89 )
90 try:
91 executions = response["data"]
92 if executions:
93 status = executions[0]["status"]
94 if status is None:
95 status = "Never Ran"
96 else:
97 status = "No executions found"
98 return WorkflowExecutionStatusResponseModel(last_run=status)
99 except Exception as e:
100 logger.error(f"Failed to get workflow executions with error: {e}")
101 raise HTTPException(
102 status_code=500,
103 detail=f"Failed to get workflow executions with error: {e}",
104 )
105
106
107 async def execute_workflow(workflow_execution_body: RequestWorkflowExecutionModel):
108 """
109 Execute a workflow.
110
111 Args:
112 workflow_execution_body (WorkflowExecutionBodyModel): The workflow execution body model.
113
114 Returns:
115 WorkflowExecutionResponseModel: The response model containing the workflow executions.
116
117 Raises:
118 HTTPException: If the workflow is not found.
119 """
120 logger.info(f"Executing workflow with ID: {workflow_execution_body.workflow_id}")
121 response = ExecuteWorklow(
122 **(
123 await send_post_request(
124 f"/api/v1/workflows/{workflow_execution_body.workflow_id}/execute",
125 {"execution_argument": workflow_execution_body.execution_argument},
126 )
127 )["data"],
128 )
129 logger.info(f"Response from executing workflow: {response}")
130 try:
131 if response.success:
132 workflow_completed = await wait_for_workflow_execution_results(response)
133 if workflow_completed:
134 logger.info(f"Successfully executed workflow with ID: {workflow_execution_body.workflow_id}")
135 return await get_workflow_exectution_results(response)
136 else:
137 raise HTTPException(
138 status_code=404,
139 detail="Failed to execute workflow",
140 )
141 except Exception as e:
142 logger.error(f"Failed to execute workflow with error: {e}")
143 raise HTTPException(
144 status_code=500,
145 detail=f"Failed to execute workflow with error: {e}",
146 )
147
148
149 async def wait_for_workflow_execution_results(execution: ExecuteWorklow):
150 """
151 Function to get the workflow results until the status of `FINISHED` is reached.
152 """
153 logger.info(f"Retrieving workflow execution results for execution ID: {execution.execution_id}")
154 for i in range(10):
155 try:
156 response = await send_post_request(
157 "/api/v1/streams/results",
158 {"execution_id": str(execution.execution_id), "authorization": str(execution.authorization)},
159 )
160 status = response.get("data", {}).get("status")
161 if status == "FINISHED":
162 logger.info(f"Workflow execution with ID {execution.execution_id} has finished")
163 return True
164 except Exception as e:
165 logger.error(f"Error retrieving workflow execution results: {e}")
166 await asyncio.sleep(2**i)
167 logger.info(f"Workflow execution with ID {execution.execution_id} did not finish after 5 attempts")
168 raise HTTPException(
169 status_code=500,
170 detail=f"Workflow execution with ID {execution.execution_id} did not finish after 5 attempts",
171 )
172
173
174 async def get_workflow_exectution_results(execution: ExecuteWorklow):
175 """
176 Function to get the workflow results.
177 """
178 logger.info(f"Retrieving workflow execution results for execution ID: {execution.execution_id}")
179 response = await send_post_request(
180 "/api/v1/streams/results",
181 {"execution_id": str(execution.execution_id), "authorization": str(execution.authorization)},
182 )
183 return response.get("data", {})