Skip to content

Commit a15693c

Browse files
authored
Fix celery service functions error (#462)
1 parent 5e60d9c commit a15693c

File tree

6 files changed

+68
-41
lines changed

6 files changed

+68
-41
lines changed

backend/app/task/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323

2424
你可以通过 `CELERY_BROKER` 控制消息代理选择,它支持 redis 和 rabbitmq
2525

26-
对于本地调试,我们建议使用 redis
26+
对于本地调试,建议使用 redis
2727

28-
对于线上环境,我们强制使用 rabbitmq
28+
对于线上环境,强制使用 rabbitmq

backend/app/task/api/v1/task.py

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,38 +14,45 @@
1414
router = APIRouter()
1515

1616

17-
@router.get('', summary='获取所有可执行任务模块', dependencies=[DependsJwtAuth])
17+
@router.get('', summary='获取可执行任务', dependencies=[DependsJwtAuth])
1818
async def get_all_tasks() -> ResponseModel:
19-
tasks = task_service.get_list()
19+
tasks = await task_service.get_list()
2020
return response_base.success(data=tasks)
2121

2222

23-
@router.get('/running', summary='获取正在执行的任务', dependencies=[DependsJwtAuth])
24-
async def get_current_task() -> ResponseModel:
25-
task = task_service.get()
26-
return response_base.success(data=task)
27-
28-
29-
@router.get('/{tid}/status', summary='获取任务状态', dependencies=[DependsJwtAuth])
30-
async def get_task_status(tid: Annotated[str, Path(description='任务ID')]) -> ResponseModel:
31-
status = task_service.get_status(tid)
23+
@router.get(
24+
'/{tid}',
25+
summary='获取任务详情',
26+
deprecated=True,
27+
description='此接口被视为作废,建议使用 flower 查看任务详情',
28+
dependencies=[DependsJwtAuth],
29+
)
30+
async def get_task_detail(tid: Annotated[str, Path(description='任务ID')]) -> ResponseModel:
31+
status = task_service.get_detail(tid=tid)
3232
return response_base.success(data=status)
3333

3434

35-
@router.get('/{tid}', summary='获取任务结果', dependencies=[DependsJwtAuth])
36-
async def get_task_result(tid: Annotated[str, Path(description='任务ID')]) -> ResponseModel:
37-
task = task_service.get_result(tid)
38-
return response_base.success(data=task)
35+
@router.post(
36+
'/{tid}',
37+
summary='撤销任务',
38+
dependencies=[
39+
Depends(RequestPermission('sys:task:revoke')),
40+
DependsRBAC,
41+
],
42+
)
43+
async def revoke_task(tid: Annotated[str, Path(description='任务ID')]) -> ResponseModel:
44+
task_service.revoke(tid=tid)
45+
return response_base.success()
3946

4047

4148
@router.post(
42-
'/{name}',
49+
'',
4350
summary='执行任务',
4451
dependencies=[
4552
Depends(RequestPermission('sys:task:run')),
4653
DependsRBAC,
4754
],
4855
)
4956
async def run_task(obj: RunParam) -> ResponseModel:
50-
task = task_service.run(name=obj.name, args=obj.args, kwargs=obj.kwargs)
57+
task = task_service.run(obj=obj)
5158
return response_base.success(data=task)

backend/app/task/celery_task/tasks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77

88
@celery_app.task(name='task_demo_async')
99
async def task_demo_async() -> str:
10-
await sleep(10)
10+
await sleep(20)
1111
return 'test async'

backend/app/task/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class TaskSettings(BaseSettings):
3131

3232
# Celery
3333
CELERY_BROKER: Literal['rabbitmq', 'redis'] = 'redis'
34-
CELERY_BACKEND_REDIS_PREFIX: str = 'fba:celery_'
34+
CELERY_BACKEND_REDIS_PREFIX: str = 'fba:celery:'
3535
CELERY_BACKEND_REDIS_TIMEOUT: int = 5
3636
CELERY_TASK_PACKAGES: list[str] = [
3737
'app.task.celery_task',
Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,53 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
3+
34
from celery.exceptions import NotRegistered
45
from celery.result import AsyncResult
6+
from starlette.concurrency import run_in_threadpool
57

68
from backend.app.task.celery import celery_app
9+
from backend.app.task.schema.task import RunParam
10+
from backend.common.dataclasses import TaskResult
711
from backend.common.exception.errors import NotFoundError
812

913

1014
class TaskService:
1115
@staticmethod
12-
def get_list():
13-
filtered_tasks = []
14-
tasks = celery_app.tasks
15-
for key, value in tasks.items():
16-
if not key.startswith('celery.'):
17-
filtered_tasks.append({key, value})
18-
return filtered_tasks
19-
20-
@staticmethod
21-
def get():
22-
return celery_app.current_worker_task
16+
async def get_list():
17+
registered_tasks = await run_in_threadpool(celery_app.control.inspect().registered)
18+
tasks = list(registered_tasks.values())[0]
19+
return tasks
2320

2421
@staticmethod
25-
def get_status(uid: str):
22+
def get_detail(*, tid: str):
2623
try:
27-
task_result = AsyncResult(id=uid, app=celery_app)
24+
result = AsyncResult(id=tid, app=celery_app)
2825
except NotRegistered:
2926
raise NotFoundError(msg='任务不存在')
30-
return task_result.status
27+
return TaskResult(
28+
result=result.result,
29+
traceback=result.traceback,
30+
status=result.state,
31+
name=result.name,
32+
args=result.args,
33+
kwargs=result.kwargs,
34+
worker=result.worker,
35+
retries=result.retries,
36+
queue=result.queue,
37+
)
3138

3239
@staticmethod
33-
def get_result(uid: str):
40+
def revoke(*, tid: str):
3441
try:
35-
task_result = AsyncResult(id=uid, app=celery_app)
42+
result = AsyncResult(id=tid, app=celery_app)
3643
except NotRegistered:
3744
raise NotFoundError(msg='任务不存在')
38-
return task_result.result
45+
result.revoke(terminate=True)
3946

4047
@staticmethod
41-
def run(*, name: str, args: list | None = None, kwargs: dict | None = None):
42-
task = celery_app.send_task(name=name, args=args, kwargs=kwargs)
43-
return task
48+
def run(*, obj: RunParam):
49+
task: AsyncResult = celery_app.send_task(name=obj.name, args=obj.args, kwargs=obj.kwargs)
50+
return task.task_id
4451

4552

4653
task_service: TaskService = TaskService()

backend/common/dataclasses.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,16 @@ class AccessToken:
5252
class RefreshToken:
5353
refresh_token: str
5454
refresh_token_expire_time: datetime
55+
56+
57+
@dataclasses.dataclass
58+
class TaskResult:
59+
result: str
60+
traceback: str
61+
status: str
62+
name: str
63+
args: list | None
64+
kwargs: dict | None
65+
worker: str
66+
retries: int | None
67+
queue: str | None

0 commit comments

Comments
 (0)