diff --git a/main.py b/main.py index ecdde0a..b3e76cd 100644 --- a/main.py +++ b/main.py @@ -5,6 +5,7 @@ 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 @@ -106,6 +107,20 @@ def main(): 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()) # 让机器人一直跑 diff --git a/utils/markdown_to_image.py b/utils/markdown_to_image.py index 8f4fe0c..5b71127 100644 --- a/utils/markdown_to_image.py +++ b/utils/markdown_to_image.py @@ -610,6 +610,32 @@ def _get_browser_manager() -> _PersistentBrowser: return _BROWSER_MANAGER +async def warmup_md2img_browser(timeout_seconds: int = 45) -> bool: + """预热 Markdown 转图浏览器(异步)。 + + 设计目的: + 1. 服务启动后提前完成浏览器冷启动,减少首个截图任务的等待和失败概率; + 2. 不执行实际业务截图,仅确保常驻浏览器已可用。 + """ + try: + manager = _get_browser_manager() + await asyncio.wait_for(manager.ensure_browser(), timeout=max(10, int(timeout_seconds))) + logger.info("[md2img] 浏览器预热完成") + return True + except Exception as e: + logger.error(f"[md2img] 浏览器预热失败: {e}") + return False + + +def warmup_md2img_browser_sync(timeout_seconds: int = 45) -> bool: + """预热 Markdown 转图浏览器(同步包装,适合在线程中调用)。""" + try: + return asyncio.run(warmup_md2img_browser(timeout_seconds=timeout_seconds)) + except Exception as e: + logger.error(f"[md2img] 同步预热执行失败: {e}") + return False + + async def html_to_image(html_content, output_image): manager = _get_browser_manager() await manager.screenshot(html_content, output_image)