【发布时间】:2011-06-22 08:49:00
【问题描述】:
我发现了一个奇怪的错误undefined method `run_callbacks' for nil:NilClass,并能够使用此示例代码重现它。
基本上问题是活动记录超时(默认为 5 秒)但抛出未定义的方法异常,这对我来说似乎是错误的。
但无论如何,处理这个问题的正确方法是什么?在我的真实代码中,我有一堆忙于实际工作的线程,但偶尔我会遇到这个错误。所以想象puts 是真正的代码。发生这种情况时,我希望现有线程继续工作。
threads = []
10.times do |n|
threads << Thread.new {
ActiveRecord::Base.connection_pool.with_connection do |conn|
puts "#{n} #{conn}"
res = conn.execute("select sleep(6)", :async => true)
end
}
end
# block and wait for all threads to finish
threads.each { |t| puts "joined" ; t.join }
rescue Exception => e
puts $!, $@
end
如果我按原样运行此代码,则会出现异常。如果我将睡眠时间减少到 4 秒,我不会。这是 6s sleep 的输出。
joined
0 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c6380>
1 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c5548>
2 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4fe4>
3 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c4a80>
4 #<ActiveRecord::ConnectionAdapters::Mysql2Adapter:0xb73c451c>
joined
joined
joined
joined
joined
undefined method `run_callbacks' for nil:NilClass
/usr/lib/ruby/gems/1.8/gems/activerecord-2.2.2/lib/active_record/connection_adapters/abstract/connection_pool.rb:212:in `checkin'
sqltst.rb:31:in `join'
sqltst.rb:31
sqltst.rb:31:in `each'
sqltst.rb:31
【问题讨论】:
-
如果你尝试在线程内捕获异常,你会得到同样的错误吗?
-
如何处理它取决于您查询的性质。我假设由于它们在单独的线程中运行,因此每个线程中的查询在上下文中是相互隔离的。在这种情况下,我肯定会处理线程本身的错误。超时重试 3 次,然后设置“线程返回码”并退出线程。如果您正在进行更新,那么当然可以将它们打包到一个事务中 - ActiveRecord 支持这一点。
-
如果您只是想编写代码以继续运行,您是否尝试过在代码块末尾添加“rescue nil”?
标签: mysql ruby-on-rails multithreading activerecord exception-handling