This commit is contained in:
27942
2026-03-03 02:13:33 +08:00
parent 5526f2d048
commit 3788197358
4 changed files with 270 additions and 151 deletions

View File

@@ -14,7 +14,7 @@ from rest_framework.decorators import api_view
from common.protocol import TaskStatus, TaskType
from server.core.response import api_success, api_error
from server.models import BossAccount, TaskCreate, TaskLog
from server.models import BossAccount, TaskCreate, TaskLog, Task
from server.serializers import TaskCreateSerializer
from server.core.worker_manager import worker_manager
from server.core.task_dispatcher import task_dispatcher
@@ -29,19 +29,27 @@ def _format_timestamp(ts: float) -> str:
def _task_to_dict(t) -> dict:
""" TaskInfo 转为可序列化字典。"""
"""任务实例Task ORM转为可序列化字典。"""
return {
"task_id": t.task_id,
"task_type": t.task_type.value if hasattr(t.task_type, "value") else str(t.task_type),
"status": t.status.value if hasattr(t.status, "value") else str(t.status),
"task_type": str(t.task_type),
"status": str(t.status),
"worker_id": t.worker_id,
"account_name": t.account_name,
"params": t.params,
"progress": t.progress,
"account_name": getattr(t, "account_name", None),
"params": t.params or {},
"progress": getattr(t, "progress", None),
"result": t.result,
"error": t.error,
"created_at": _format_timestamp(t.created_at),
"updated_at": _format_timestamp(t.updated_at),
"created_at": (
t.created_at.strftime("%Y-%m-%dT%H:%M:%S")
if hasattr(t.created_at, "strftime")
else _format_timestamp(t.created_at)
),
"updated_at": (
t.updated_at.strftime("%Y-%m-%dT%H:%M:%S")
if hasattr(t.updated_at, "strftime")
else _format_timestamp(t.updated_at)
),
}
@@ -135,38 +143,20 @@ def _is_task_log_for_account(task_log: TaskLog, account: BossAccount) -> bool:
def _list_tasks_by_account(account: BossAccount, task_status: Optional[TaskStatus], limit: Optional[int] = 50) -> list:
"""
聚合某账号的任务列表:
1) 内存任务(实时)
2) TaskLog 历史任务(重启后可查)
按账号维度查询任务列表,完全基于 Task 表。
- 不再依赖内存中的 TaskInfo
- 你可以直接修改数据库中 Task.status/Task.result 等字段来影响这里的返回。
"""
items_by_task_id = {}
# limit=None 用于分页场景下先取全量,再切片;此处给内存任务查询一个足够大的上限
memory_limit = 10000 if limit is None else max(limit * 3, 100)
memory_tasks = task_dispatcher.list_tasks(worker_id=account.worker_id, status=task_status, limit=memory_limit)
for t in memory_tasks:
if t.account_name != account.browser_name:
continue
items_by_task_id[t.task_id] = _task_to_dict(t)
db_qs = TaskLog.objects.filter(worker_id=account.worker_id).order_by("-created_at")
qs = Task.objects.filter(
worker_id=account.worker_id,
account_name=account.browser_name,
).order_by("-created_at")
if task_status:
db_qs = db_qs.filter(status=task_status.value)
qs = qs.filter(status=task_status.value if hasattr(task_status, "value") else str(task_status))
# 多取一些做过滤,避免因为条件匹配损耗导致结果太少
db_logs = db_qs if limit is None else db_qs[: max(limit * 8, 200)]
for task_log in db_logs:
if not _is_task_log_for_account(task_log, account):
continue
if task_log.task_id in items_by_task_id:
continue
items_by_task_id[task_log.task_id] = _task_log_to_dict(task_log, account_name=account.browser_name)
merged = list(items_by_task_id.values())
merged.sort(key=lambda item: item.get("created_at") or "", reverse=True)
if limit is None:
return merged
return merged[:limit]
if limit is not None:
qs = qs[:limit]
return [_task_to_dict(t) for t in qs]
@api_view(["GET", "POST"])
@@ -200,8 +190,13 @@ def task_list(request):
)
return api_success(_list_tasks_by_account(account, task_status=task_status, limit=limit))
tasks = task_dispatcher.list_tasks(worker_id=wid, status=task_status, limit=limit)
return api_success([_task_to_dict(t) for t in tasks])
qs = Task.objects.all().order_by("-created_at")
if wid:
qs = qs.filter(worker_id=wid)
if task_status:
qs = qs.filter(status=task_status.value if hasattr(task_status, "value") else str(task_status))
qs = qs[:limit]
return api_success([_task_to_dict(t) for t in qs])
# POST: 提交新任务
data = request.data.copy()