ruby-on-rails - 提交嵌套事务

标签 ruby-on-rails postgresql activerecord

假设我有一个方法可以在用户范围内提供对 API 客户端的访问,并且 API 客户端将在用户 OAuth token 过期时自动更新它们。

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 token (因为上面的过程也被视为事务的一部分):

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 返回的数据的持久化需要在事务中发生。即使父事务失败,我如何确保提交对用户 token 的更新。

最佳答案

您是否尝试过在新线程中打开一个新的数据库连接,并在该线程中执行更新

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!

   # Now open new thread
   # In the new thread open new db connection, separate from the one already opened
   # In the new connection execute update only for the tokens
   # Close new connection and new thread
   Thread.new do
      ActiveRecord::Base.connection_pool.with_connection do |connection|
         connection.execute("Your SQL statement that will update the user tokens")        
      end
   end.join
}

希望对你有帮助

关于ruby-on-rails - 提交嵌套事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44597262/

相关文章:

ruby-on-rails - Rails 与 Heroku : How to download a CSV created by a rake task

ruby-on-rails - 在 Formtastic 的同一个 LI 元素中包含两个输入

java - 无法连接到 PostgreSQLContainer : java. io.EOFException

ruby-on-rails - 我怎么知道 Rails 已经加载/缓存了一个 Activerecord 类属性?

sql - 如何将这两个 PostgreSQL 语句合并为一个用于 Rails 3 应用程序?

ruby-on-rails - rails 3.1 : Querying Postgres for records within a time range

ruby-on-rails - 找不到 id=1 的 CycleRoad (rails)

ruby - 哪个 Ruby ORM 支持 PostgreSQL 数组数据类型?

python - 为什么 Psycopg 提供 `cursor` 的方法 (`copy_to()` , `copy_from()` ),而不是调用 `cursor.execute()` 发送 `COPY` 命令?

ruby-on-rails - 验证或不验证 bool 字段