尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

ADK-Python 捕获 StaleSessionError 后如何重读会话并重放 append_event 修复并发写冲突

ADK-Python 捕获 StaleSessionError 后如何重读会话并重放 append_event 修复并发写冲突 ADK-Python 捕获 StaleSessionError 后如何重读会话并重放 append_event 修复并发写冲突【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python在 ADK-Python 中用DatabaseSessionService、SqliteSessionService或FirestoreSessionService持久化会话时如果两个进程或两个写者持有同一个会话的副本并先后调用append_event后写入的一方会收到StaleSessionError。这是 ADK 的乐观并发保护你手里的内存Session已经落后于存储中的副本如果不拦截你的追加会静默覆盖另一个写者刚写入的历史。本文给出排查这个异常、修正错误捕获方式以及按官方恢复路径重读会话、重放append_event的完整操作。先确认这个异常什么时候会抛StaleSessionError只由做了并发写检查的三种会话服务在append_event时抛出DatabaseSessionService、SqliteSessionService、FirestoreSessionService。触发条件是你持有的内存Session在你读取之后、写入之前已经被别人更新过。InMemorySessionService不做这项检查文档也明确说明它不适合多线程生产使用所以如果你在开发环境没看到这个异常不代表生产环境不会有。异常的完整定义见 异常说明会话生命周期见 Session and BaseSessionService。第一步检查是否被宽泛的except ValueError吞掉了这是排查StaleSessionError时最容易被忽略的一点。StaleSessionError为了向后兼容继承了ValueError所以会话代码附近任何except ValueError都会把它静默吞掉。错误的写法看起来像严谨的错误处理实际效果是把这一轮的对话历史直接扔掉try: await session_service.append_event(session, event) except ValueError: logger.warning(bad event, skipping)用户侧的症状是对话缺了一整段且日志里只有一行无关紧要的 warning。如果你正在排查会话历史突然少了几条事件先全局搜索except ValueError是否覆盖了append_event调用。修正方式是捕获具体类型并且把StaleSessionError子句放在任何ValueError子句之前Python 取第一个匹配的except子句宽泛的放前面会遮住下面所有窄的try: await session_service.append_event(session, event) except StaleSessionError: # 恢复逻辑见下一步 ... except ValueError: # 其他真正的参数错误 ...如果一个except子句确实需要同时覆盖多个 ADK 异常用元组显式列出例如except (StaleSessionError, SessionNotFoundError)。ADK 的六个自定义异常没有公共基类不存在能兜住所有 ADK 错误的单个except。导入方式只有包级入口from google.adk.errors import StaleSessionError注意反向的坑AlreadyExistsError、NotFoundError、ToolExecutionError继承的是Exception而不是ValueErrorexcept ValueError对它们一无所获。第二步重读会话并对新副本重放 append_eventStaleSessionError是六个 ADK 异常中唯一有官方恢复路径的用get_session重新读取会话再对新副本重放本次append_event。完整写法try: await session_service.append_event(session, event) except StaleSessionError: session await session_service.get_session( app_namesession.app_name, user_idsession.user_id, session_idsession.id, ) await session_service.append_event(session, event)两个细节决定这段代码能否直接跑通会话由(app_name, user_id, session_id)三元组唯一标识get_session三个参数都必须传不能只靠session_id。重放前先用旧副本上的app_name、user_id、id重新读取拿到的是包含其他写者最新写入的会话副本对新副本追加时存储层会再次做版本校验通过后才落库。如果你在写自定义后端继承BaseSessionServiceappend_event里要先持久化事件再调用await super().append_event(session, event)保持内存副本同步否则自己也会制造 stale 会话。第三步验证写入没有再丢事件修复是否生效用一次get_session读回即可判断检查两点被重放的event出现在session.events里该事件actions.state_delta中的键值已合并进session.state。仓库单元测试对同一场景的断言可以作为参照见 测试文件对一个 stale 会话直接append_event会抛StaleSessionError消息匹配modified in storage失败的追加不会落库读回的会话events只包含已提交的事件stale 事件携带的sk3键在state中不存在。执行你的恢复逻辑后读回的会话应同时包含其他写者的事件和你重放的事件两者都不缺。错误消息、异常细节与文档间的口径异常消息来自服务实现中的常量见 database_session_service.pyThe session has been modified in storage since it was loaded. Please reload the session before appending more events.按这个文本可以精确定位是否命中了 stale 检查。StaleSessionError没有定义自己的构造函数也没有.message属性str(StaleSessionError())是空字符串——不要依赖读异常上的默认文本来判断直接用类型判断。Session 指南在Detecting a stale session一节里说DatabaseSessionServiceraisesValueError与 异常文档的StaleSessionError不矛盾后者就是前者的具体子类两份文档指向同一个异常。六个 ADK 异常之间没有结构化错误码或 cause 字段除ToolExecutionError的error_type外消息字符串是全部信息。修复完成后如果你的会话由Runner驱动日常代码通常只直接调用服务来创建、列举和删除会话get_session与append_event由Runner代劳上面这段手动恢复逻辑适用于你直接调用会话服务的场景例如自定义服务封装或多进程共享同一会话的部署。【免费下载链接】adk-pythonAn open-source, code-first Python toolkit for building, evaluating, and deploying sophisticated AI agents with flexibility and control.项目地址: https://gitcode.com/GitHub_Trending/ad/adk-python创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表