2011-01-16 6 views
3

Ich bin mit Rails 3 und Ruby 1.9.Threading in Schienen Konsole mit aktiver Datensatz nicht findet Modell in der Datenbank

Ich bin mit zwei Methoden in verschiedenen Schienen-Tests (und in der Konsole). Die Methoden heißen index_cases und index_new_cases und die Methodenkörper sind unten gezeigt. Der Inhalt der index_new_cases Methode ist wahrscheinlich nicht relevant (ich indexiere ModelCase Informationen mit dem Sunspot Edelstein), aber ich überlasse es dort der Vollständigkeit halber.

Ich habe 3 case_numbers. Jeder case_number entspricht einem ModelCase in der Datenbank (das heißt, es gibt 3 ModelCase Datensätze in der db).

Wenn ich solche mit 3 case_numbers Tests auf der index_cases Methode auszuführen, die index_new_cases Methode abrufen KEINE Fälle die ModelCase.where… Methode. Allerdings, wenn ich das „Einfädeln“ ruft in der index_cases Methode zu entfernen, die index_new_cases Funktion nun ruft alle drei Fälle und indiziert sie richtig.

Kann jemand mir erklären, warum meine Themen nicht die Datensätze der Datenbank finden? Ist meine Threading-Implementierung falsch? Danke!

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 

Diese Methode (ohne Gewinde) funktioniert allerdings nur in Tests zu finden und Datenbankeinträge meiner Index

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 
+0

Können Sie die Log-Informationen für die Abfrage erstellen und es mit der nicht-Thread-Version vergleichen? – zetetic

+0

Letztes Mal, als ich versuchte, ähnliche Dinge zu tun, fand ich heraus, Active Record ist nicht thread-sicher oder in der Lage, ich habe Probleme bei der Verbindung mit der Datenbank. während ich in einen activecord Pool oder eine Multiprocess-Lösung wechselte, scheint das zu funktionieren. Übrigens war ich auch auf 1,9 actrecrod3. – c2h2

+0

Ich wurde verrückt, bis ich die Antwort unten sah. Es hat es für mich getan; Überprüfen Sie meinen Kommentar für Details =) Sie möchten @ MGPalmer Antwort annehmen – Abdo

Antwort

3

ich, ein sehr ähnliches Problem hatte.

Das Problem liegt in den Transaktionen, die in Testfällen verwendet werden (wenn transaktionale Fixtures aktiviert sind) - Änderungen an Daten sind für andere Verbindungen nicht sichtbar, solange die Transaktion nicht festgeschrieben ist.

Siehe http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

Als Konsequenz Änderungen an der Datenbank werden nicht außerhalb Ihrer Verbindung gesehen, bis der Vorgang abgeschlossen ist.

Threads sollten eine neue Verbindung zur Datenbank haben. Und da bei der Verwendung transaktionaler Fixtures der gesamte Testlauf in eine Transaktion eingeschlossen wird, ist nichts darin für Threads sichtbar, außer was sie selbst erstellen.

Sie können die Transaktionen deaktivieren, zum Glück auch für Einzeltests: http://ar.rubyonrails.org/classes/Fixtures.html

+0

Danke! Der Link oben war Timeout, http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html tat es für mich. Überprüfen Sie die Antwort zu http://stackoverflow.com/questions/3774742/activerecord-rollback-does-not-work-in-rails-test; Klasse FooTest Abdo

+0

Tausend mal ja ...mein Eintrag mit 'id: 2' hat mich umgebracht! – RichieAHB

Verwandte Themen