eri*_*cvg 15 activerecord ruby-on-rails rufus-scheduler
我正在使用rufus-scheduler来运行一些频繁的作业,这些作业使用ActiveRecord对象执行一些不同的任务.如果存在任何类型的网络或postgresql打嗝,即使在恢复之后,所有线程都会抛出以下错误,直到重新启动该进程:
ActiveRecord :: ConnectionTimeoutError(无法在5秒内获得数据库连接(等待5.000122687秒).最大池大小当前为5;考虑增加它.
重新启动postgres可以轻松复制错误.我已经尝试过玩游戏(最多15个),但是没有运气.
这让我相信连接只处于陈旧状态,我认为这将通过调用来解决clear_stale_cached_connections!.
有没有更可靠的模式来做到这一点?
传递的块是一个简单的选择和更新活动记录调用,并且恰好与AR对象有关.
rufus工作:
scheduler.every '5s' do
db do
DataFeed.update #standard AR select/update
end
end
Run Code Online (Sandbox Code Playgroud)
包装:
def db(&block)
begin
ActiveRecord::Base.connection_pool.clear_stale_cached_connections!
#ActiveRecord::Base.establish_connection # this didn't help either way
yield block
rescue Exception => e
raise e
ensure
ActiveRecord::Base.connection.close if ActiveRecord::Base.connection
ActiveRecord::Base.clear_active_connections!
end
end
Run Code Online (Sandbox Code Playgroud)
Mar*_*eus 13
Rufus调度程序为每个作业启动一个新线程.另一方面,ActiveRecord无法共享线程之间的连接,因此需要为特定线程分配连接.
当你的线程还没有连接时,它将从池中获取一个.(如果池中的所有连接都在使用中,它将等待,直到从另一个线程返回一个.最终超时并抛出ConnectionTimeoutError)
完成后,您有责任将其恢复到池中,在Rails应用程序中,这是自动完成的.但是如果你管理自己的线程(如rufus那样),你必须自己做.
幸运的是,有一个api:如果你把你的代码放在一个with_connection块中,它将从池中获得一个连接,并在完成后释放它
ActiveRecord::Base.connection_pool.with_connection do
#your code here
end
Run Code Online (Sandbox Code Playgroud)
在你的情况下:
def db
ActiveRecord::Base.connection_pool.with_connection do
yield
end
end
Run Code Online (Sandbox Code Playgroud)
应该做的伎俩....
bas*_*gys -1
我不太了解 rufus-scheduler,但我有一些想法。
第一个问题可能是 rufus-scheduler 上的错误,该错误无法正确检查数据库连接。如果是这种情况,唯一的解决方案是像您已经做的那样手动清除过时的连接,并将您的问题告知 rufus-scheduler 的作者。
可能发生的另一个问题是您的 DataFeed 操作需要很长时间,并且因为它每 5 秒执行一次,Rails 就会耗尽数据库连接,但这不太可能。
| 归档时间: |
|
| 查看次数: |
5532 次 |
| 最近记录: |