- 实现 JWT 认证中间件,保护配置管理和任务删除接口 - 修复 ConfigView 登录按钮(Vue 3 inject 替代 $root) - 页面刷新时通过 /api/auth/me 校验 token 有效性 - max_concurrent_builds 修改后运行时即时生效 - 实现钉钉 webhook 通知(构建成功/失败自动推送) - 删除未使用的 useWebSocket composable - log_streamer 使用 LOG_QUEUE_MAX_SIZE 配置常量
86 lines
2.7 KiB
Python
86 lines
2.7 KiB
Python
"""并行打包队列管理"""
|
|
import asyncio
|
|
from typing import Dict, Callable, Optional
|
|
from datetime import datetime
|
|
|
|
from .log_streamer import log_streamer
|
|
|
|
|
|
class BuildQueue:
|
|
"""打包任务队列"""
|
|
|
|
def __init__(self, max_concurrent: int = 2):
|
|
self._max_concurrent = max_concurrent
|
|
self._semaphore = asyncio.Semaphore(max_concurrent)
|
|
self._queue: asyncio.Queue = asyncio.Queue()
|
|
self._running_tasks: Dict[str, asyncio.Task] = {}
|
|
self._workers: list = []
|
|
self._started = False
|
|
|
|
async def start(self):
|
|
"""启动工作线程"""
|
|
if self._started:
|
|
return
|
|
self._started = True
|
|
for i in range(self._max_concurrent):
|
|
worker = asyncio.create_task(self._worker(f"worker-{i}"))
|
|
self._workers.append(worker)
|
|
|
|
async def _worker(self, name: str):
|
|
"""工作协程"""
|
|
while True:
|
|
task_id, build_func = await self._queue.get()
|
|
try:
|
|
await self._semaphore.acquire()
|
|
try:
|
|
self._running_tasks[task_id] = asyncio.current_task()
|
|
await build_func(task_id)
|
|
finally:
|
|
self._running_tasks.pop(task_id, None)
|
|
self._semaphore.release()
|
|
except Exception as e:
|
|
await log_streamer.emit_error(task_id, f"任务异常: {str(e)}")
|
|
finally:
|
|
self._queue.task_done()
|
|
|
|
async def submit(self, task_id: str, build_func: Optional[Callable] = None):
|
|
"""提交打包任务"""
|
|
if not self._started:
|
|
await self.start()
|
|
|
|
if build_func is None:
|
|
from .build_service import run_build_task
|
|
build_func = run_build_task
|
|
|
|
await self._queue.put((task_id, build_func))
|
|
await log_streamer.emit(task_id, "任务已加入队列,等待执行...")
|
|
|
|
def cancel(self, task_id: str):
|
|
"""取消任务"""
|
|
task = self._running_tasks.get(task_id)
|
|
if task and not task.done():
|
|
task.cancel()
|
|
|
|
def update_max_concurrent(self, new_max: int):
|
|
"""更新最大并发数(运行时生效)"""
|
|
if new_max == self._max_concurrent:
|
|
return
|
|
old = self._max_concurrent
|
|
self._max_concurrent = new_max
|
|
# 调整信号量:增加并发时 release 额外的许可,减少时由自然消费收敛
|
|
if new_max > old:
|
|
for _ in range(new_max - old):
|
|
self._semaphore.release()
|
|
|
|
@property
|
|
def queue_size(self) -> int:
|
|
return self._queue.qsize()
|
|
|
|
@property
|
|
def running_count(self) -> int:
|
|
return len(self._running_tasks)
|
|
|
|
|
|
# 全局单例
|
|
build_queue = BuildQueue()
|