"""持久化任务执行者;获取连接级锁后才恢复或领取任务。""" from datetime import datetime from pathlib import Path from app.core.tplus_db import get_tplus_session_factory, resolve_tplus_settings from app.core.tplus_lock import TPlusBusyError, sync_lock from app.repositories import tplus_repository as repository from app.services.tplus import task_service from app.services.tplus.relationship_audit import TPlusRelationshipAudit from app.services.tplus.sync_service import TPlusSyncService def run_once(session, source_factory=None): """返回本轮处理的批次号;忙锁或队列为空时不假称已执行。""" try: with sync_lock(session): task_service.recover_running(session) batch = repository.next_queued(session) if batch is None: session.rollback() return None batch.status, batch.started_at = "RUNNING", datetime.now() session.commit() _execute(session, batch, source_factory) return batch.batch_no except TPlusBusyError: session.rollback() return None def _execute(session, batch, source_factory): try: settings = resolve_tplus_settings(task_service.get_settings()) if batch.source_database and batch.source_database != settings.t_plus_database: raise RuntimeError("任务排队后的源账套配置已改变") factory = source_factory or get_tplus_session_factory() with factory() as source: if batch.sync_mode == "AUDIT": root = Path(settings.t_plus_query_dir) if settings.t_plus_query_dir else None report = TPlusRelationshipAudit(source, root).run() batch.audit_result_json = report batch.source_record_count = sum(row["row_count"] for row in report["receipt_kinds"]) batch.finished_at, batch.status = datetime.now(), "SUCCEEDED" if report["relationship_status"] != "OBSERVED": task_service.fail_batch(session, batch, "TYPE_UNRESOLVED") else: session.commit() else: TPlusSyncService(source, session).execute_claimed(batch) except BaseException as exc: session.rollback() task_service.fail_batch( session, batch, "INTERRUPTED" if isinstance(exc, (KeyboardInterrupt, SystemExit)) else "EXECUTION_ERROR", ) if isinstance(exc, (KeyboardInterrupt, SystemExit)): raise