【发布时间】:2019-09-27 00:13:09
【问题描述】:
假设我有一个方法可以在用户范围内提供对 API 客户端的访问,并且 API 客户端会在用户 OAuth 令牌过期时自动更新它们。
class User < ActiveRecord::Base
def api
ApiClient.new access_token: oauth_access_token,
refresh_token: oauth_refresh_token,
on_oauth_refresh: -> (tokens) {
# This proc will be called by the API client when an
# OAuth refresh occurs
update_attributes({
oauth_access_token: tokens[:access_token],
oauth_refresh_token: tokens[:refresh_token]
})
}
end
end
如果我在 Rails 事务中使用此 API 并发生刷新,然后发生错误 - 我无法保留新的 OAuth 令牌(因为上面的 proc 也被视为事务的一部分):
u = User.first
User.transaction {
local_info = Info.create!
# My tokens are expired so the client automatically
# refreshes them and calls the proc that updates them locally.
external_info = u.api.get_external_info(local_info.id)
# Now when I try to locally save the info returned by the API an exception
# occurs (for example due to validation). This rolls back the entire
# transaction (including the update of the user's new tokens.)
local_info.info = external_info
local_info.save!
}
我正在简化示例,但基本上 API 的使用和 API 返回的数据的持久性需要在事务中发生。即使父事务失败,我如何确保对用户令牌的更新得到提交。
【问题讨论】:
-
把它放在事务之外,不是吗?
-
不幸的是,没有。 “嵌套事务”由我无法控制的 API 客户端调用。想象一下,在我的交易中,我需要使用一个 API,而我的 OAuth 令牌过期了。 API 客户端刷新了我的令牌,但无法持久保存它们,因为下游事务失败。
-
也许你需要
Autonomous Transactions。 This article 可以帮助您掌握这个概念并将其应用到您的 Ruby 场景中。 -
感谢您的链接。你知道任何可以帮助解决这个问题的 Ruby/Rails 抽象层吗?我宁愿避免编写存储过程。
-
没有。 Ruby 不在我的工具集中。
标签: ruby-on-rails postgresql activerecord