SQLAlchemy `onupdate=` typo on 6 `trigger.py` `updated_at` columns silently breaks ORM auto-refresh

在 Dify 自托管(Source)环境中运行主分支代码,通过 ORM 操作触发相关的服务(如 api/services/trigger/* 、 schedule_service.py 、 webhook_service.py 等)进行更新后,发现 updated_at 字段长时间未变化,可能影响依

快速结论:该报错发生在 Dify 自托管环境下,当通过 ORM 更新 TriggerProviderSubscriptionAppTriggerSubscriptionAppTriggerWorkflowTriggerLogWorkflowTriggerStatus 等模型的记录时,updated_at 字段不会自动刷新(始终保持原值)。优先排查 api/models/trigger.py 文件中 6 个 updated_at 列是否错误地使用了 server_onupdate=func.current_timestamp(),应替换为 onupdate=func.current_timestamp()

问题场景

在 Dify 自托管(Source)环境中运行主分支代码,通过 ORM 操作触发相关的服务(如 api/services/trigger/*schedule_service.pywebhook_service.py 等)进行更新后,发现 updated_at 字段长时间未变化,可能影响依赖该时间戳的业务逻辑(如缓存失效、同步检查等)。

报错原文

# api/models/trigger.py 中 6 个 affected columns 的错误模式
server_default=func.current_timestamp(),
server_onupdate=func.current_timestamp(),  # typo: server_onupdate expects FetchedValue, not a Python callable

# 正确的写法(该文件中 line 534 已正确使用)
onupdate=func.current_timestamp()

原因分析

在 SQLAlchemy ORM 中,server_onupdate= 参数期望接收一个 FetchedValue 对象(用于标记数据库侧由触发器/默认值更新的列),而非常见的 func.current_timestamp() 这样的 Python 可调用对象。SQLAlchemy 会静默接受 func.current_timestamp() 作为 server_onupdate 的值,但不会在 ORM 执行 UPDATE 语句后自动刷新该列的值,导致 updated_at 永远停留在插入时的原始值。这是 api/models/trigger.py 中 6 个列独有的类型错误,代码库其他 70+ 个模型均统一使用 onupdate=func.current_timestamp()

环境排查

  • 确认使用的是 Dify main branch(uncommitted)版本。
  • 确认部署模式为 Self Hosted(Source)。
  • 检查 api/models/trigger.py 文件中的 updated_at 列声明:line 128、183、213、373、433、482。

解决步骤

  1. 打开 api/models/trigger.py 文件。
  2. 定位到受影响的 6 个 updated_at 列(行号参考:128、183、213、373、433、482)。
  3. 将每个列声明中的 server_onupdate=func.current_timestamp() 替换为 onupdate=func.current_timestamp()
  4. 对于 AppTrigger.updated_at(line 482),将 server_onupdate=naive_utc_now() 替换为 onupdate=naive_utc_now(),保持 Python 侧模式一致。
  5. 保留 server_default=func.current_timestamp() 不变,确保 INSERT 行为不受影响。
  6. 无需执行数据库迁移,因为该变更仅影响 ORM 层面的 Python 钩子,不改变 DDL 列定义。

验证方法

修改代码后,通过 ORM 更新任意受影响模型的记录(例如调用 session.commit() 后),检查 updated_at 字段是否自动刷新为当前时间。也可以在更新前记录时间戳,更新后重新查询该记录,确认 updated_at 与更新操作的时间匹配。该修复不影响直接通过 SQL 语句进行的更新。

参考来源

langgenius/dify #38407

GamsGo AI

AI 工具推荐

想把多个 AI 模型放在一个入口?

GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。

了解 GamsGo AI

推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。

这个方案解决了吗?

celebrityanime
celebrityanime
文章: 16214

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注