使用contextvars重构上下文标记功能

This commit is contained in:
jingrow 2025-11-01 03:46:11 +08:00
parent 92700c638a
commit 99491e0b9b
2 changed files with 13 additions and 12 deletions

View File

@ -6,7 +6,7 @@ import functools
import inspect import inspect
import logging import logging
import os import os
import threading from contextvars import ContextVar
from jingrow.model.page import Page from jingrow.model.page import Page
from jingrow.config import Config from jingrow.config import Config
from jingrow.utils.jingrow_api import upload_file_to_jingrow from jingrow.utils.jingrow_api import upload_file_to_jingrow
@ -14,8 +14,7 @@ from jingrow.utils.jingrow_api import upload_file_to_jingrow
_local = {} _local = {}
# 【通用执行上下文标记】用于标记当前调用链的来源,防止循环触发等场景 # 【通用执行上下文标记】用于标记当前调用链的来源,防止循环触发等场景
# 使用 thread-local 存储,轻量且精确(同一线程内有效) _update_source_context: ContextVar[Optional[str]] = ContextVar('update_source', default=None)
_update_source_context = threading.local()
# 统一 Jingrow 日志记录器(仅为本模块及调用方提供最小可用输出,不修改全局 root logger # 统一 Jingrow 日志记录器(仅为本模块及调用方提供最小可用输出,不修改全局 root logger
_root_logger = logging.getLogger("jingrow") _root_logger = logging.getLogger("jingrow")
@ -71,9 +70,10 @@ def skip_hooks(source: str = "agent"):
""" """
设置上下文标记表示当前调用链来自指定来源如智能体执行 设置上下文标记表示当前调用链来自指定来源如智能体执行
用于跳过某些钩子防止循环触发等场景 用于跳过某些钩子防止循环触发等场景
使用 contextvars.ContextVar支持同步和异步上下文传播
""" """
try: try:
_update_source_context.source = source _update_source_context.set(source)
except Exception: except Exception:
pass pass
@ -81,10 +81,10 @@ def skip_hooks(source: str = "agent"):
def restore_hooks(): def restore_hooks():
""" """
清除上下文标记恢复正常的钩子执行 清除上下文标记恢复正常的钩子执行
注意contextvars 会自动管理上下文生命周期通常在 try-finally 中使用
""" """
try: try:
if hasattr(_update_source_context, 'source'): _update_source_context.set(None)
delattr(_update_source_context, 'source')
except Exception: except Exception:
pass pass
@ -92,9 +92,10 @@ def restore_hooks():
def get_hook_source() -> Optional[str]: def get_hook_source() -> Optional[str]:
""" """
获取当前调用链的来源标识用于判断是否跳过某些钩子 获取当前调用链的来源标识用于判断是否跳过某些钩子
在异步环境中也能正确获取上下文值
""" """
try: try:
return getattr(_update_source_context, 'source', None) return _update_source_context.get()
except Exception: except Exception:
return None return None

View File

@ -38,14 +38,14 @@ def run_agent(pg=None, method=None, event=None, page=None, **kwargs):
"""本地版 Local Ai Agent 事件驱动机制。 """本地版 Local Ai Agent 事件驱动机制。
- 支持按 pagetype module 分组合并去重 - 支持按 pagetype module 分组合并去重
- condition 支持 Jinja2 表达式 - condition 支持 Jinja2 表达式
- 使用上下文标记防止无限循环 - 使用 contextvars 上下文标记防止无限循环支持同步和异步场景
""" """
# 兼容多种调用方式 # 兼容多种调用方式
pg = pg or page pg = pg or page
method = event or method or kwargs.get("event") method = event or method or kwargs.get("event")
# 【防无限循环】检查上下文标记:如果当前调用来自智能体执行,跳过 # 【防无限循环】检查上下文标记:如果当前调用来自智能体执行,跳过
# 使用轻量级 thread-local 上下文标记,防止循环触发 # 使用 contextvars.ContextVar 上下文标记,支持同步和异步场景,防止循环触发
if jingrow.get_hook_source() == "agent": if jingrow.get_hook_source() == "agent":
return return