2026-03-19 10:38:11 +08:00
|
|
|
|
"""
|
2026-03-19 16:01:09 +08:00
|
|
|
|
回忆录后台处理器:debounce 聚合后派发 Celery 任务
|
|
|
|
|
|
实际回忆录生成由 memoir_tasks.process_memoir_segments 调用 MemoirOrchestrator 完成
|
2026-03-19 10:38:11 +08:00
|
|
|
|
"""
|
2026-03-19 14:36:14 +08:00
|
|
|
|
|
2026-03-19 10:38:11 +08:00
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Dict, List
|
|
|
|
|
|
|
|
|
|
|
|
from app.core.logging import get_logger
|
|
|
|
|
|
from app.core.task_tracker import task_tracker
|
|
|
|
|
|
|
|
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BackgroundTaskRunner:
|
|
|
|
|
|
def __init__(self, debounce_seconds: int = 5) -> None:
|
|
|
|
|
|
self.debounce_seconds = debounce_seconds
|
|
|
|
|
|
self._pending: Dict[str, List[str]] = {}
|
|
|
|
|
|
self._timers: Dict[str, object] = {}
|
|
|
|
|
|
|
|
|
|
|
|
async def _submit_task(self, user_id: str, segment_ids: List[str]) -> str | None:
|
|
|
|
|
|
try:
|
|
|
|
|
|
from app.tasks.memoir_tasks import process_memoir_segments
|
|
|
|
|
|
|
|
|
|
|
|
result = process_memoir_segments.delay(user_id, segment_ids)
|
|
|
|
|
|
task_id = result.id
|
|
|
|
|
|
await task_tracker.add_task(user_id, task_id, "memoir")
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
"已提交 Celery 任务: user_id=%s, task_id=%s, segments=%s",
|
|
|
|
|
|
user_id,
|
|
|
|
|
|
task_id,
|
|
|
|
|
|
len(segment_ids),
|
|
|
|
|
|
)
|
|
|
|
|
|
return task_id
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error("提交 Celery 任务失败: %s", e)
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
async def queue_message(self, user_id: str, segment_id: str) -> None:
|
|
|
|
|
|
import asyncio
|
|
|
|
|
|
|
|
|
|
|
|
self._pending.setdefault(user_id, []).append(segment_id)
|
|
|
|
|
|
if user_id in self._timers:
|
|
|
|
|
|
self._timers[user_id].cancel()
|
|
|
|
|
|
|
|
|
|
|
|
async def delayed_submit():
|
|
|
|
|
|
try:
|
|
|
|
|
|
await asyncio.sleep(self.debounce_seconds)
|
|
|
|
|
|
segment_ids = self._pending.pop(user_id, [])
|
|
|
|
|
|
if segment_ids:
|
|
|
|
|
|
await self._submit_task(user_id, segment_ids)
|
|
|
|
|
|
except asyncio.CancelledError:
|
|
|
|
|
|
pass
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.error("延迟提交任务失败: %s", e)
|
|
|
|
|
|
|
|
|
|
|
|
self._timers[user_id] = asyncio.create_task(delayed_submit())
|
|
|
|
|
|
|
|
|
|
|
|
async def flush_pending(self, user_id: str) -> str | None:
|
|
|
|
|
|
if user_id in self._timers:
|
|
|
|
|
|
self._timers[user_id].cancel()
|
|
|
|
|
|
del self._timers[user_id]
|
|
|
|
|
|
segment_ids = self._pending.pop(user_id, [])
|
|
|
|
|
|
if segment_ids:
|
|
|
|
|
|
return await self._submit_task(user_id, segment_ids)
|
|
|
|
|
|
return None
|