假设我有一个方法,它提供对用户范围内的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返回的数据的持久化需要在事务中发生。如何确保即使父事务失败,也能提交对用户令牌的更新?
3条答案
按热度按时间kyxcudwk1#
你试过在新线程中打开一个新的数据库连接,并在这个线程中执行更新吗
希望这能帮上忙
hiz5n14c2#
Nermin的(被接受的)答案是正确的。
此处记录:Rails指导线程和并发
bnl4lu3b3#
上一个问题中的discussion可能对你有帮助。看起来你可以设置一个
requires_new: true
标志,并将子事务标记为子事务。