Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails 4.2:如何动态更改线程使用的连接?_Ruby On Rails_Ruby_Multithreading_Activerecord_Database Connection - Fatal编程技术网

Ruby on rails Rails 4.2:如何动态更改线程使用的连接?

Ruby on rails Rails 4.2:如何动态更改线程使用的连接?,ruby-on-rails,ruby,multithreading,activerecord,database-connection,Ruby On Rails,Ruby,Multithreading,Activerecord,Database Connection,如何更改一个线程的连接?我想这样做: # slow query process at background Thread.new do User.all { |user| user.update_attributes(some_field: (rand * 100).to_i) } end # more slow query process 100000.times { User.where(some_field_2: (rand * 100).to_i).first } 我希望这两个线

如何更改一个线程的连接?我想这样做:

# slow query process at background
Thread.new do
  User.all { |user| user.update_attributes(some_field: (rand * 100).to_i) }
end

# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
我希望这两个线程(主线程和我创建的线程)异步运行,但我发现Rails使用一个连接来实现这一点。因此,我所有同时运行两个查询并争取时间的努力都失败了——Rails将我的请求缩减到一个单一的同步池中。我也尝试了以下方法,但尽管Rails创建了一个新连接,ActiveRecord(“用户”)却没有使用它:

# slow query process at background
Thread.new do
  conn = ActiveRecord::Base.connection_pool.checkout()
  User.all {|user| user.update_attributes(some_field: (rand * 100).to_i) }
  ActiveRecord::Base.connection_pool.checkin(conn)
end
我曾尝试设置“ActiveRecord::Base.connection=conn”,但也没有成功


有没有可能每个线程都有自己的连接?如何设置线程连接?

好的,我知道了。但我必须对“检索连接”进行一些修改才能实现这一点。我把这个放在我的应用程序上。rb:

module ActiveRecord
  module ConnectionAdapters
    class ConnectionHandler
      def retrieve_connection(klass) #:nodoc:
        pool = retrieve_connection_pool(klass)
        raise ConnectionNotEstablished, "No connection pool for #{klass}" unless pool
        conn = Thread.current["connection"] || pool.connection
        raise ConnectionNotEstablished, "No connection for #{klass} in connection pool" unless conn
        conn
      end
    end
  end
end
我只是将“conn=pool.connection”修改为“conn=Thread.current[“connection”]| | pool.connection”。这允许我使用自定义线程变量定义连接。有了这个黑客,我的代码看起来像这样:

# slow query process at background
Thread.new do
  Thread.current["connection"] = ActiveRecord::Base.connection_pool.checkout()
  User.all {|user| user.update_attributes(some_field: (rand * 100).to_i) }
  ActiveRecord::Base.connection_pool.checkin(Thread.current["connection"])    
end

# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
或者更好,为每次更新创建一个新线程:

# slow query process at background
User.all do |user|
  Thread.new do
    Thread.current["connection"] = ActiveRecord::Base.connection_pool.checkout()
    user.update_attributes(some_field: (rand * 100).to_i)
    ActiveRecord::Base.connection_pool.checkin(Thread.current["connection"])
  end
end

# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }
PS:这满足了我的需要,但我想知道是否有一个本机方法来更改线程的连接。我的做法太难看了:/因此,如果你知道更好的方法,请分享。

根据,你必须将应用程序代码包装在executor块中

试试这个(对于Rails版本:4):

假设您在
config/database.yml
中的池大小值大于1,这应该可以工作

Thread.new do
  ActiveRecord::Base.connection_pool.with_connection do
    User.all { |user| user.update_attributes(some_field: (rand * 100).to_i) }
  end
end

# more slow query process
100000.times { User.where(some_field_2: (rand * 100).to_i).first }