Files
abot/main.py
liuwei 6af91756d3 支持服务启动后自动预热转图浏览器
变更项:1) markdown_to_image 新增预热方法 warmup_md2img_browser/warmup_md2img_browser_sync,用于提前拉起常驻浏览器。2) main.py 启动流程新增后台预热线程,服务启动后自动执行转图浏览器预热。3) 预热失败仅记录日志不阻塞主服务,运行期仍可按需自动重建浏览器。4) 补充中文注释说明预热目的与降级策略。
2026-04-17 09:28:36 +08:00

140 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
import asyncio
import threading
from admin.GlancesMonitor import GlancesMonitor
from utils.decorator.async_job import async_job
from utils.markdown_to_image import warmup_md2img_browser_sync
from configuration import Config
from robot import Robot
from loguru import logger
from utils.sehuatang.sehuatang_bot import SehuatangCrawler
# 普通日志不附带 traceback避免 debug/info 文件被异常堆栈刷屏。
def _plain_log_format(record):
record["exception"] = None
return "{time:YYYY-MM-DD HH:mm:ss.SSS} | {level:<8} | {name}:{function}:{line} - {message}\n"
def _error_log_format(record):
return (
"{time:YYYY-MM-DD HH:mm:ss.SSS} | {level:<8} | {name}:{function}:{line} - {message}\n"
"{exception}"
)
# INFO 日志(包含 INFO、DEBUG但不包含 WARNING、ERROR
logger.add(
f"logs/wx_info.log",
level="INFO",
filter=lambda record: record["level"].name in ["INFO", "DEBUG"],
rotation="10 MB",
retention="7 days",
encoding="utf-8",
format=_plain_log_format,
backtrace=False,
diagnose=False,
)
# ERROR 日志(仅 ERROR 及以上)
logger.add(
f"logs/wx_error.log",
level="ERROR",
rotation="10 MB",
retention="7 days",
encoding="utf-8",
format=_error_log_format,
backtrace=True,
diagnose=True,
)
# ERROR 日志(仅 ERROR 及以上)
logger.add(
f"logs/wx_debug.log",
level="DEBUG",
rotation="10 MB",
retention="7 days",
encoding="utf-8",
format=_plain_log_format,
backtrace=False,
diagnose=False,
)
def main():
config = Config()
# 创建机器人实例
robot = Robot(config)
robot.LOG.info(f"ABOT服务 正在启动...")
# 初始化并启动wechat_ipad客户端
if robot.init_wechat_ipad():
robot.LOG.info("wechat_ipad客户端启动成功")
else:
robot.LOG.error("wechat_ipad客户端启动失败")
# 注册定时任务
jobs(robot)
# 启动Dashboard服务器
try:
# 创建Dashboard服务器实例共享robot对象
from admin.dashboard.server import DashboardServer
dashboard_server = DashboardServer(robot_instance=robot)
# 在单独的线程中启动Dashboard服务器
dashboard_thread = threading.Thread(target=dashboard_server.run, daemon=True)
dashboard_thread.start()
robot.LOG.info(f"Dashboard服务器已在 http://{dashboard_server.host}:{dashboard_server.port} 启动")
except Exception as e:
robot.LOG.error(f"Dashboard服务器启动失败: {e}")
try:
robot.LOG.debug(f"开始启动GlancesMonitor")
# 初始化 Glances 监控
monitor = GlancesMonitor(
email_sender=robot.email_sender,
host=config.glances.get("host"),
port=config.glances.get("port"),
cpu_threshold=80.0,
load_threshold=16, # 自动设为 CPU 核心数 * 2
io_threshold=100.0,
disk_usage_threshold=70.0,
handle_threshold=20000,
recipient=config.email.get("alert_recipient")
)
monitor.run()
except Exception as e:
robot.LOG.error(f"GlancesMonitor服务器启动失败: {e}")
# 启动后异步预热 Markdown 转图浏览器,降低首个转图任务冷启动失败概率。
try:
def _warmup_md2img():
ok = warmup_md2img_browser_sync(timeout_seconds=60)
if ok:
robot.LOG.info("Markdown 转图浏览器预热成功")
else:
robot.LOG.warning("Markdown 转图浏览器预热失败,运行期将按需重试")
warmup_thread = threading.Thread(target=_warmup_md2img, daemon=True)
warmup_thread.start()
except Exception as e:
robot.LOG.error(f"启动 Markdown 转图预热线程失败: {e}")
robot.LOG.info(f"=" * 50)
asyncio.run(async_job.run_all())
# 让机器人一直跑
robot.keep_running_and_block_process()
def jobs(robot: Robot):
# 系统级定时任务统一改为数据库驱动,不再在 main.py 里硬编码维护。
# 这里保留入口,只负责按表配置重新加载,便于运行时刷新。
if hasattr(robot, "system_job_loader") and robot.system_job_loader:
robot.system_job_loader.reload_from_db()
if __name__ == "__main__":
main()