"""虎牙任务批次执行器(入口聚合;功能域已拆分到 huya_runner_*.py)。""" from __future__ import annotations from concurrent.futures import ThreadPoolExecutor, as_completed from sqlalchemy.orm import joinedload from ..database import SessionLocal from datetime import datetime, timezone from ..models import HuyaAccount, HuyaTask from core.huya.cookie_utils import normalize_huya_cookie from .huya_service import HUYA_CONFIG_FIELDS, ensure_huya_config, huya_config_value from .huya_runner_core import HuyaBatchRunnerCore, huya_batch_registry # noqa: F401 (huya_batch_registry 供 routers 重导出) from .huya_runner_bind import BindMixin from .huya_runner_goods import GoodsMixin from .huya_runner_recharge import RechargeMixin class HuyaBatchRunner( HuyaBatchRunnerCore, BindMixin, GoodsMixin, RechargeMixin, ): """批量执行虎牙任务(功能域 Mixin 聚合 + 批次调度)。""" def _execute_one(self, task_id: int, account_info: dict, config_info: dict, total: int): worker_db = SessionLocal() try: task = worker_db.query(HuyaTask).filter(HuyaTask.id == task_id).first() account = worker_db.query(HuyaAccount).filter(HuyaAccount.id == account_info["account_id"]).first() if not task or not account: return if self._stop.is_set(): self._mark_task(worker_db, task, "stopped", "任务已停止") return task.status = "running" task.message = "执行中" task.finished_at = None worker_db.commit() with self._counter_lock: self._started += 1 current = self._started name = self._account_name(account_info) self._push_log("info", f"[{current}/{total}] 开始虎牙任务: {name}") if self.task_type not in { "query_points", "get_bind_qr", "confirm_bind", "query_game_name", "query_exchange_records", "refresh_goods", "refresh_recharge_goods", "exchange_goods", "create_recharge_order", }: self._mark_task(worker_db, task, "failed", "该虎牙任务执行器暂未实现") self._push_log("warning", f"[{current}] {name} 暂未实现: {self.task_type}") return try: if self.task_type == "query_points": self._execute_query_points(worker_db, task, account, account_info, config_info) elif self.task_type == "refresh_goods": self._execute_refresh_goods(worker_db, task, account, account_info, config_info) elif self.task_type == "refresh_recharge_goods": self._execute_refresh_recharge_goods(worker_db, task, account, account_info, config_info) elif self.task_type == "exchange_goods": self._execute_exchange_goods(worker_db, task, account, account_info, config_info) elif self.task_type == "create_recharge_order": self._execute_create_recharge_order(worker_db, task, account, account_info, config_info) elif self.task_type == "get_bind_qr": self._execute_get_bind_qr(worker_db, task, account, account_info, config_info) elif self.task_type == "confirm_bind": self._execute_confirm_bind(worker_db, task, account, account_info, config_info) elif self.task_type == "query_game_name": self._execute_query_game_name(worker_db, task, account, account_info, config_info) elif self.task_type == "query_exchange_records": self._execute_query_exchange_records(worker_db, task, account, account_info, config_info) worker_db.refresh(task) if task.status == "success": self._push_log("success", f"[{current}] {name} {task.message}") else: self._push_log("error", f"[{current}] {name} {task.message}") except Exception as exc: self._mark_task(worker_db, task, "error", f"执行异常: {exc}") self._push_log("error", f"[{current}] {name} 执行异常: {exc}") finally: worker_db.close() def run(self): """在线程中执行虎牙批次任务。""" self._push_log( "info", f"虎牙批次 {self.batch_id} 开始,共执行 {self.task_type},并发数: {self.concurrency}", ) try: config = ensure_huya_config(self.db) config_info = { field: huya_config_value(field, getattr(config, field, None)) for field in HUYA_CONFIG_FIELDS } tasks = ( self.db.query(HuyaTask) .options(joinedload(HuyaTask.account)) .filter(HuyaTask.batch_id == self.batch_id) .order_by(HuyaTask.id.asc()) .all() ) task_infos = [] for task in tasks: account = task.account if not account: task.status = "error" task.message = "账号不存在" task.finished_at = datetime.now(timezone.utc) continue task.status = "pending" task.message = "等待执行" task.finished_at = None task_infos.append({ "task_id": task.id, "account_info": { "account_id": account.id, "uid": account.uid or "", "yyuid": account.yyuid or "", "username": account.username or "", "nickname": account.nickname or "", "cookie": normalize_huya_cookie(account.cookie or ""), }, }) self.db.commit() total = len(task_infos) if total == 0: self._push_log("warning", "没有可执行的虎牙任务") self._push_log("result", "") return with ThreadPoolExecutor(max_workers=self.concurrency) as executor: futures = [] for item in task_infos: if self._stop.is_set(): self._push_log("warning", "任务已停止,跳过剩余账号") break futures.append(executor.submit( self._execute_one, item["task_id"], item["account_info"], config_info, total, )) for future in as_completed(futures): try: future.result() except Exception as exc: self._push_log("error", f"虎牙 Worker 异常: {exc}") self._push_log("info", f"虎牙批次 {self.batch_id} 完成") self._push_log("result", "") except Exception as exc: self._push_log("error", f"虎牙批次执行异常: {exc}") self._push_log("result", "") finally: self.db.close()