具有活动记录的rails控制台中的线程在数据库中找不到Model

时间:2011-01-16 02:59:36

标签: ruby-on-rails ruby multithreading thread-safety

我正在使用Rails 3和Ruby 1.9。

我在各种rails测试中(以及在控制台中)运行了2种方法。这些方法称为index_casesindex_new_cases,方法体如下所示。 index_new_cases方法的内容可能不相关(我使用Sunspot gem索引ModelCase信息),但我将其留在那里是为了完整。

我有3 case_numbers。每个case_number匹配数据库中的ModelCase(即数据库中有3个ModelCase条记录。)

当我使用这些case_numbersindex_cases方法运行测试时,index_new_cases方法不会使用ModelCase.where…方法检索任何案例。但是,如果我删除index_cases方法中的“线程”调用,index_new_cases函数现在会检索所有3个案例并对其进行正确索引。

有人可以向我解释为什么我的线程无法找到数据库记录吗? 我的线程实现是错误的吗? 谢谢!

  def index_cases(case_numbers)
    threads = []
    case_numbers.each_slice(500) do |slice_of_case_numbers|
      threads << Thread.new(slice_of_case_numbers) do |a_slice|
        index_new_cases(a_slice)
      end
    end
    threads.each {|thr| thr.join}
  end

  def index_new_cases(case_numbers)
    cs = ModelCase.where(case_number: case_numbers).includes(:child_tables)
    puts cs.size # prints 0 with threading and 3 without threading
    Sunspot.index(cs)
    Sunspot.commit
  end

此方法(没有线程)可以正常查找和索引我的数据库记录

  def index_cases(case_numbers)
    #threads = []
    case_numbers.each_slice(500) do |slice_of_case_numbers|
      #threads << Thread.new(slice_of_case_numbers) do |a_slice|
        index_new_cases(slice_of_case_numbers)
     #end
    end
    #threads.each {|thr| thr.join}
  end

1 个答案:

答案 0 :(得分:4)

我有一个非常类似的问题,但只是在测试中。

问题在于测试用例中使用的事务(当事务装置打开时) - 只要事务未提交,其他连接就不会看到对数据的更改。

请参阅http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

  

因此,在您之外看不到对数据库的更改   连接直到操作完成。

线程应该与数据库建立新连接。而且由于在使用事务性工具时,整个测试运行都包含在一个事务中,除了他们自己创建的内容之外,线程中没有任何内容可见。

您可以关闭交易,幸运的是还可以进行单项测试:http://ar.rubyonrails.org/classes/Fixtures.html