Files
AlphaPulse/backend/src/alphapulse/news_research/worker.py
T
eezd 89da4df785
Development CI / check-and-build (push) Successful in 3m23s
GitHub Git mirror / mirror (push) Successful in 6s
Development CI / deploy-development (push) Successful in 5s
feat(news): restrict research to local sources and process frozen batches
2026-11-05 20:43:31 +08:00

83 lines
3.6 KiB
Python

"""One bounded pool for indexing, assignment and event research; no third stage."""
import asyncio
import logging
from sqlalchemy import select, text, update
from alphapulse.core.db import SessionLocal, engine
from alphapulse.news_research.models import (
ResearchSettings,
Package,
Event,
Attempt,
Version,
Batch, BatchEvent,
)
from alphapulse.news_research.service import process_package, process_event
from alphapulse.news_research import batches
logger = logging.getLogger(__name__)
async def run():
async with engine.connect() as lock:
if not await lock.scalar(text("SELECT pg_try_advisory_lock(20261030, 1)")):
raise RuntimeError("新闻AI worker 已运行")
await lock.commit()
async with SessionLocal() as session:
for stage in ("index", "assign"):
await session.execute(
update(Package)
.where(Package.state == stage + "_processing")
.values(state=stage + "_pending")
)
await session.execute(
update(Attempt)
.where(Attempt.state == "processing")
.values(state="failed", error="进程中断,待重试")
)
await session.execute(
update(Event).where(Event.state == "processing").values(state="pending")
)
await session.execute(
update(Version)
.where(Version.state == "processing")
.values(state="failed", error="进程中断,待重试")
)
await session.execute(update(BatchEvent).where(BatchEvent.state == 'processing').values(state='pending'))
await session.commit()
tasks = {}
try:
while True:
for task in list(tasks):
if task.done():
tasks.pop(task)
try:
task.result()
except Exception:
logger.exception("新闻研究任务失败")
async with SessionLocal() as session:
settings = await session.get(ResearchSettings, 1)
if settings and settings.enabled:
batch = await session.scalar(select(Batch).where(
Batch.phase.in_(['assigning', 'researching'])).order_by(Batch.id).limit(1))
if batch is None:
batch = await batches.freeze(session, settings)
settings = await session.get(ResearchSettings, 1, populate_existing=True, with_for_update=True)
if batch is not None and settings.enabled:
active = set(tasks.values())
actions = await batches.actions(session, batch, active,
max(0, settings.config.get('concurrency', 3) - len(tasks)))
await session.commit()
for stage, identifier in actions:
call = (process_event(identifier, settings.config, force=True)
if stage == 'event' else process_package(identifier, settings.config))
tasks[asyncio.create_task(call)] = (stage, identifier)
await asyncio.sleep(1)
finally:
await asyncio.gather(*tasks, return_exceptions=True)
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO)
asyncio.run(run())