mirror of
https://github.com/Nezumi-2711/astrbot_plugin_qq_group_daily_analysis.git
synced 2026-09-22 13:38:43 +00:00
fix(thread-safety): 已为
templates.py 中的 Jinja2 环境缓存添加线程安全保护,具体改动如下: 使用双重检查锁定(Double-Checked Locking)保护缓存访问 读取缓存时加锁,避免多线程同时读取时的数据竞争 创建新环境后再次加锁检查,防止高并发下重复创建相同模板的环境 原代码中 _envs 字典会通过 asyncio.to_thread(self._get_env_sync) 被多个线程同时访问和修改,存在数据竞争风险。现在通过 threading.Lock 确保了线程安全。
This commit is contained in:
@@ -5,6 +5,7 @@ HTML模板模块
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import threading
|
||||
|
||||
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
||||
|
||||
@@ -19,16 +20,19 @@ class HTMLTemplates:
|
||||
self.config_manager = config_manager
|
||||
# 设置模板根目录
|
||||
self.base_dir = os.path.join(os.path.dirname(__file__), "templates")
|
||||
# 缓存不同模板的Jinja2环境
|
||||
# 缓存不同模板的Jinja2环境(多线程安全)
|
||||
self._envs = {}
|
||||
self._env_lock = threading.Lock()
|
||||
|
||||
def _get_env_sync(self) -> Environment:
|
||||
"""获取当前配置的模板环境(同步版本,供 asyncio.to_thread 调用)"""
|
||||
template_name = self.config_manager.get_report_template()
|
||||
|
||||
# 如果环境已缓存且配置未变
|
||||
if template_name in self._envs:
|
||||
return self._envs[template_name]
|
||||
# 如果环境已缓存且配置未变(使用锁保证多线程安全)
|
||||
with self._env_lock:
|
||||
env = self._envs.get(template_name)
|
||||
if env is not None:
|
||||
return env
|
||||
|
||||
template_dir = os.path.join(self.base_dir, template_name)
|
||||
if not os.path.exists(template_dir):
|
||||
@@ -41,7 +45,14 @@ class HTMLTemplates:
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
)
|
||||
self._envs[template_name] = env
|
||||
|
||||
# 使用双重检查锁定,避免在高并发下重复创建相同 template_name 的 env
|
||||
with self._env_lock:
|
||||
existing = self._envs.get(template_name)
|
||||
if existing is not None:
|
||||
return existing
|
||||
self._envs[template_name] = env
|
||||
|
||||
return env
|
||||
|
||||
async def _get_env_async(self) -> Environment:
|
||||
|
||||
Reference in New Issue
Block a user