#!/usr/bin/env python3 # -*- coding: utf-8 -*- from __future__ import annotations import os import time from services.runtime import get_logger, get_socketio from services.state import safe_get_account, safe_iter_task_status_items def status_push_worker() -> None: """后台线程:按间隔推送排队/运行中任务的状态更新(可节流)。""" logger = get_logger() try: push_interval = float(os.environ.get("STATUS_PUSH_INTERVAL_SECONDS", "1")) except Exception: push_interval = 1.0 push_interval = max(0.5, push_interval) socketio = get_socketio() from services.tasks import get_task_scheduler scheduler = get_task_scheduler() last_queued_emit: dict[str, dict] = {} while True: try: now_ts = time.time() queue_snapshot = scheduler.get_queue_state_snapshot() pending_total = int(queue_snapshot.get("pending_total", 0) or 0) running_total = int(queue_snapshot.get("running_total", 0) or 0) running_by_user = queue_snapshot.get("running_by_user") or {} positions = queue_snapshot.get("positions") or {} status_items = safe_iter_task_status_items() active_queued_ids: set[str] = set() for account_id, status_info in status_items: status = status_info.get("status") if status not in ("运行中", "排队中"): continue user_id = status_info.get("user_id") if not user_id: continue pos = positions.get(account_id) or {} # 排队中的账号不需要每秒全量推送:仅在队列位置/总数变化或到达保底间隔时推送,避免拖慢整体性能 if status != "运行中": active_queued_ids.add(account_id) running_user = int(running_by_user.get(int(user_id), 0) or 0) prev = last_queued_emit.get(account_id) or {} prev_ts = float(prev.get("ts", 0) or 0) should_emit = False if not prev: should_emit = True elif ( prev.get("queue_ahead") != pos.get("queue_ahead") or prev.get("queue_position") != pos.get("queue_position") or prev.get("pending_total") != pending_total or prev.get("running_total") != running_total or prev.get("running_user") != running_user ): should_emit = True elif now_ts - prev_ts >= max(push_interval, 2.0): should_emit = True if not should_emit: continue last_queued_emit[account_id] = { "ts": now_ts, "queue_ahead": pos.get("queue_ahead"), "queue_position": pos.get("queue_position"), "pending_total": pending_total, "running_total": running_total, "running_user": running_user, } else: last_queued_emit.pop(account_id, None) account = safe_get_account(user_id, account_id) if not account: continue account_data = account.to_dict() account_data.update( { "queue_pending_total": pending_total, "queue_running_total": running_total, "queue_ahead": pos.get("queue_ahead"), "queue_position": pos.get("queue_position"), "queue_is_vip": pos.get("is_vip"), "queue_running_user": int(running_by_user.get(int(user_id), 0) or 0), } ) socketio.emit("account_update", account_data, room=f"user_{user_id}") if status != "运行中": continue progress = status_info.get("progress", {}) or {} progress_data = { "account_id": account_id, "stage": status_info.get("detail_status", ""), "total_items": account.total_items, "browsed_items": progress.get("items", 0), "total_attachments": account.total_attachments, "viewed_attachments": progress.get("attachments", 0), "start_time": status_info.get("start_time", 0), "elapsed_seconds": account_data.get("elapsed_seconds", 0), "elapsed_display": account_data.get("elapsed_display", ""), "queue_pending_total": pending_total, "queue_running_total": running_total, "queue_ahead": pos.get("queue_ahead"), "queue_position": pos.get("queue_position"), "queue_running_user": int(running_by_user.get(int(user_id), 0) or 0), } socketio.emit("task_progress", progress_data, room=f"user_{user_id}") # 清理已不在排队的记录,避免 dict 无限制增长 if last_queued_emit: for acc_id in list(last_queued_emit.keys()): if acc_id not in active_queued_ids: last_queued_emit.pop(acc_id, None) time.sleep(push_interval) except Exception as e: logger.debug(f"状态推送出错: {e}") time.sleep(push_interval)