diff --git a/backend/app/chat/log.py b/backend/app/chat/log.py index 7a104110..b00e99f2 100644 --- a/backend/app/chat/log.py +++ b/backend/app/chat/log.py @@ -197,12 +197,13 @@ async def stream(turn_id: str, after: int, *, active: Callable[[], Awaitable[str yield PING -async def purge(now: datetime, *, retain_days: float = RETAIN_DAYS, limit: int = PURGE_BATCH) -> list[str]: +async def purge(now: datetime | None = None, *, retain_days: float = RETAIN_DAYS, limit: int = PURGE_BATCH) -> list[str]: """结束超过 retain_days 天的轮次整轮删事件日志(见模块说明),交回清了哪几轮。任务行、conversation_turns 那一行不动。 结束的时刻按任务的 finished_at,没记的按 updated_at。""" + from app.db.base import utcnow from app.db.models_chat import ChatTurnEvent, ChatTurnJob - cutoff = now - timedelta(days=retain_days) + cutoff = (now or utcnow()) - timedelta(days=retain_days) async with SessionLocal() as session: ended = select(ChatTurnJob.id).where(ChatTurnJob.status.in_(FINISHED), func.coalesce(ChatTurnJob.finished_at, ChatTurnJob.updated_at) < cutoff) @@ -218,8 +219,8 @@ async def purge(now: datetime, *, retain_days: float = RETAIN_DAYS, limit: int = _last_purge = 0.0 -async def purge_tick(now: datetime) -> list[str]: - """调度循环每一拍调(scheduler/loop.process_due):一小时最多清一次。""" +async def purge_tick(now: datetime | None = None) -> list[str]: + """调度循环每一拍调(scheduler/loop.process_due,那一拍不一定给 now):一小时最多清一次,不给 now 按当前时间算。""" global _last_purge if time.monotonic() - _last_purge < PURGE_EVERY_S and _last_purge: return [] diff --git a/backend/tests/test_chat_turns.py b/backend/tests/test_chat_turns.py index f5f851b3..77104fe7 100644 --- a/backend/tests/test_chat_turns.py +++ b/backend/tests/test_chat_turns.py @@ -1155,3 +1155,17 @@ async def test_a_downgraded_account_that_can_still_chat_finishes_as_who_they_are row = await _row(turn_id) assert row.status == "done" and row.answer == "华东 300。" assert seen and seen[-1].username == "bob" and seen[-1].role == "user" + + +async def test_the_cleanup_tick_without_a_time_uses_now(monkeypatch): + """调度循环那一拍不一定给 now(process_due(None)):清理按当前时间算,不报错。""" + from app.scheduler import loop + + old = await _finished_turn(days_ago=turn_log.RETAIN_DAYS + 2) + monkeypatch.setattr(turn_log, "_last_purge", 0.0) + assert old in await turn_log.purge_tick() + assert await _events(old) == [] + again = await _finished_turn(days_ago=turn_log.RETAIN_DAYS + 2) + monkeypatch.setattr(turn_log, "_last_purge", 0.0) + await loop.process_due(None) + assert await _events(again) == []