Skip to content

Commit 91f5bce

Browse files
author
yinsu.zs
committed
review
Change-Id: I027ff1515728fa6859385edb49cc477cee343c64
1 parent 8869fee commit 91f5bce

5 files changed

Lines changed: 201 additions & 91 deletions

File tree

src/code/agent/exceptions/exceptions.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,45 @@ class StateTransitionError(CustomError):
1010
def __init__(self, from_state, to_state):
1111
msg = f"Illegal state transition: {from_state} -> {to_state}"
1212
super().__init__(message=msg, code=409)
13+
14+
15+
# ========== 任务管理相关异常 ==========
16+
17+
class TaskException(CustomError):
18+
"""任务管理异常基类"""
19+
def __init__(self, message: str, error_code: str = "task_error", code: int = 500):
20+
self.error_code = error_code
21+
super().__init__(code=code, message=message)
22+
23+
def to_dict(self):
24+
return {
25+
"type": "error",
26+
"error_code": self.error_code,
27+
"error_message": self.message
28+
}
29+
30+
31+
class ConfigurationException(TaskException):
32+
"""配置错误"""
33+
def __init__(self, message: str):
34+
super().__init__(message=message, error_code="configuration_error", code=500)
35+
36+
37+
class InvalidRequestException(TaskException):
38+
"""无效请求"""
39+
def __init__(self, message: str, error_code: str = "invalid_request_error"):
40+
super().__init__(message=message, error_code=error_code, code=400)
41+
42+
43+
class GPUException(TaskException):
44+
"""GPU相关异常"""
45+
def __init__(self, message: str, status_code: int = 500,
46+
error_code: str = "gpu_error", original_response: dict = None):
47+
super().__init__(message=message, error_code=error_code, code=status_code)
48+
self.original_response = original_response
49+
50+
def to_dict(self):
51+
if self.original_response and isinstance(self.original_response, dict):
52+
if "type" in self.original_response or "error" in self.original_response:
53+
return self.original_response
54+
return super().to_dict()

src/code/agent/routes/gateway_routes.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import time
66
import traceback
77

8+
import requests
89
from flask import Blueprint, Flask, jsonify, request
910
from flask_sock import Sock
1011
import websocket
@@ -67,6 +68,7 @@ def setup_routes(self):
6768
self._register_queue_handler()
6869
self._register_prompt_handler()
6970
self._register_serverless_run_handler()
71+
self._register_serverless_status_handler()
7072
self._register_history_handler()
7173
# 通过环境变量控制是否禁用工作流保存
7274
if constants.DISABLE_FLOW_SAVE:
@@ -213,6 +215,53 @@ def handle_serverless_run():
213215
"""
214216
return self.serverless_handler.handle_post_request()
215217

218+
def _register_serverless_status_handler(self):
219+
@self.bp.route("/serverless/status", methods=["GET"])
220+
@handle_exceptions(error_type="serverless_status_error", log_prefix="ServerlessStatus")
221+
def handle_serverless_status():
222+
"""
223+
处理 /api/serverless/status 请求
224+
225+
转发到 GPU 函数获取任务状态
226+
"""
227+
task_id = request.args.get("task_id", "")
228+
if not task_id:
229+
return jsonify({
230+
"type": "error",
231+
"error_code": "invalid_params",
232+
"error_message": "task_id is required"
233+
}), 400
234+
235+
# 构造 GPU URL
236+
gpu_function_url = constants.GPU_FUNCTION_URL
237+
if not gpu_function_url:
238+
return jsonify({
239+
"type": "error",
240+
"error_code": "configuration_error",
241+
"error_message": "GPU_FUNCTION_URL not configured"
242+
}), 500
243+
244+
gpu_url = f"{gpu_function_url.rstrip('/')}/api/serverless/status"
245+
246+
try:
247+
# 转发请求到 GPU
248+
resp = requests.get(
249+
gpu_url,
250+
params={"task_id": task_id},
251+
headers=dict(request.headers),
252+
timeout=30
253+
)
254+
255+
# 返回 GPU 的响应
256+
return resp.json(), resp.status_code
257+
except Exception as e:
258+
log("ERROR", f"[ServerlessStatus] Failed to forward status request: {e}")
259+
return jsonify({
260+
"type": "error",
261+
"error_code": "gpu_forward_error",
262+
"error_message": f"Failed to get status from GPU: {str(e)}"
263+
}), 500
264+
216265
def _register_history_handler(self):
217266
@self.bp.route("/history", methods=["GET"])
218267
@handle_exceptions(error_type="history_operation_error", log_prefix="History")

src/code/agent/services/gateway/handlers/prompt_handler.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
Prompt Handler
33
处理 /prompt 请求逻辑
44
"""
5+
import traceback
56
from flask import request, jsonify
67

78
from utils.logger import log
9+
from exceptions.exceptions import TaskException
810

911

1012
class PromptHandler:
@@ -42,26 +44,35 @@ def handle_post_request(self):
4244
}
4345
}), 400
4446

45-
# 转发给GPU
46-
task_id, result = self.task_manager.forward_to_gpu_async(
47-
request_body=request_data,
48-
client_id=client_id
49-
)
50-
51-
# 处理结果
52-
if task_id:
47+
try:
48+
# 转发给GPU
49+
task_id, result = self.task_manager.forward_to_gpu_async(
50+
request_body=request_data,
51+
client_id=client_id
52+
)
53+
5354
# 成功:返回ComfyUI格式
5455
return jsonify({
5556
"prompt_id": task_id,
5657
"number": 1,
5758
"node_errors": {}
5859
})
59-
else:
60-
# 失败:result 是 (status_code, error_type, error_message)
61-
status_code, error_type, error_message = result
60+
61+
except TaskException as e:
62+
log("ERROR", f"[PromptHandler] Task error: {e.message}")
63+
# 返回ComfyUI格式的错误
64+
return jsonify({
65+
"error": {
66+
"type": e.error_code,
67+
"message": e.message
68+
}
69+
}), e.code
70+
71+
except Exception as e:
72+
log("ERROR", f"[PromptHandler] Unexpected error: {str(e)}\n{traceback.format_exc()}")
6273
return jsonify({
6374
"error": {
64-
"type": error_type,
65-
"message": error_message
75+
"type": "internal_error",
76+
"message": str(e)
6677
}
67-
}), status_code
78+
}), 500

src/code/agent/services/gateway/handlers/serverless_handler.py

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@
22
Serverless Handler
33
处理 /serverless/run 请求逻辑
44
"""
5+
import traceback
56
from flask import request, jsonify
67

78
from utils.logger import log
9+
from exceptions.exceptions import TaskException
810

911
class ServerlessHandler:
1012
"""处理 /serverless/run 请求"""
@@ -35,36 +37,36 @@ def handle_post_request(self):
3537
invocation_type = request.headers.get('X-Fc-Invocation-Type', '').lower()
3638
is_async = (invocation_type == 'async')
3739

38-
if is_async:
39-
# 异步模式:立即返回任务ID
40-
log("INFO", f"[ServerlessHandler] Processing async request")
41-
task_id, result = self.task_manager.forward_to_gpu_async(
42-
request_body=body,
43-
client_id=client_id
44-
)
45-
46-
# 处理结果
47-
if task_id:
40+
try:
41+
if is_async:
42+
# 异步模式:立即返回任务ID
43+
log("INFO", f"[ServerlessHandler] Processing async request")
44+
task_id, result = self.task_manager.forward_to_gpu_async(
45+
request_body=body,
46+
client_id=client_id
47+
)
48+
4849
# 成功:返回Serverless格式
4950
return jsonify({
5051
"task_id": task_id,
5152
"status": "pending"
5253
}), 202
5354
else:
54-
# 失败:result 是 (status_code, error_type, error_message)
55-
status_code, error_type, error_message = result
56-
return jsonify({
57-
"type": "error",
58-
"error_code": error_type,
59-
"error_message": error_message
60-
}), status_code
61-
else:
62-
# 同步模式:等待GPU处理完成
63-
log("INFO", f"[ServerlessHandler] Processing sync request")
64-
65-
# 调用同步转发,直接传递完整的请求体
66-
response_data, status_code = self.task_manager.forward_to_gpu_sync(
67-
request_body=body
68-
)
55+
# 同步模式:等待GPU处理完成
56+
log("INFO", f"[ServerlessHandler] Processing sync request")
57+
response_data, status_code = self.task_manager.forward_to_gpu_sync(
58+
request_body=body
59+
)
60+
return jsonify(response_data), status_code
61+
62+
except TaskException as e:
63+
log("ERROR", f"[ServerlessHandler] Task error: {e.message}")
64+
return jsonify(e.to_dict()), e.code
6965

70-
return jsonify(response_data), status_code
66+
except Exception as e:
67+
log("ERROR", f"[ServerlessHandler] Unexpected error: {str(e)}\n{traceback.format_exc()}")
68+
return jsonify({
69+
"type": "error",
70+
"error_code": "internal_error",
71+
"error_message": str(e)
72+
}), 500

0 commit comments

Comments
 (0)