[Rails] Wielowątkowy dostęp do modelu

Witam

Mam poważny problem z wielowątkowością.
Feature powinno wyglądać tak:
Jest sobie baza danych, którą co jakiś czasz przegląda automatyczny wątek (niezależnie od użytkowników) i modyfikuje jej dane.

Moja kulawa i sztukowana implementacja wygląda tak:
Jest sobie model (nazwijmy go Host), jest sobie też klasa HostsObserver (dziedziczy po ActiveRecord::Observer), która służy do uruchomienia wątku, który przegląda bazę.
W tym wątku jest wywołanie:

hosts = Host.find(:all)

Potem wszystko jest ładnie przetwarzane i cacy.

Niestety cacy jest tylko do momentu jakiejkolwiek próby odwołania do db (z innego miejsca np. przez wyświetlenia indeksu hostów przez kontroler).
Po złapaniu wyjątku dostaję taki komunikat:

A copy of HostsObserver has been removed from the module tree but is still active!

Próbowałem używać muteksy, monitory, Thread.critical i nic, dalej to samo.

Mam nadzieję, że ktoś z Was będzie miał jakiś pomysł, jak rozwiązać ten problem.
Przynajmniej chciałbym wiedzieć czemu usuwana jest instancja HostsObserver.

Za pomoc, z góy dziękuję.

Coś kojarzę ten komunikat, spróbuj w klasie dodać linijkę “unloadable”, np.:

class Host < ActiveRecord::Observer unloadable ... end
To nie jest najlepsze rozwiązanie (nie wiem, czy ta metoda nie jest już “deprecated”) ale jeśli zadziała to może będzie wiadomo o co chodzi :-).

@qoobaa: Właśnie sprawdziłem - niestety nie działa, czyli dalej ten sam komunikat.

No to musiałbyś wystawić większy kawałek kodu, bo na razie nie wiem o co może chodzić.

[code]require ‘thread’

class HostsObserver < ActiveRecord::Observer
observe :host

def initialize
super
Thread.new do
while 1 do
begin
updateServices
rescue Exception => err
puts err.message
end
sleep (3) #nie pytaj czemu w sekundach
end

end

end

def updateServices
hosts = Host.find(:all) # jeśli tego niema to jest ok, ale być musi

bla bla bla, zabawy z hostami (zakomentowałem, więc to nie one powodują problem)

end

end[/code]
Chodzi mi tylko o to, żeby się bezproblemowo odwoływać do db.

Dodam, że takie sztuczki (jak wyżej) działały bezproblemowo w Rails 2.2.2, prowdopodobnie w Rails 2.3.2 coś się zmieniło i bardzo miło by było wiedzieć co.

//EDIT:
Jak nie kijem, to pałą - zamiast obserwatora użyję tego: BackgrounDRb.
Byle tylko się nie krzaczyło, bo mam już na czole odbitą klawiaturę :confused:

BackgrounDRb jest dobry jeśli masz długo wykonujące się skrypty odpalane przez jakieś wydarzenie pochodzące z aplikacji Rails (np. user klika w link).
Ty napisałeś “co jakiś czas” dlatego zapytam: dlaczego po prostu nie napiszesz skryptu który będzie robił to co potrzeba, umieścisz go w cron’ie który będzie go odpalał co jakiś czas np. przez script/runner ?

Wątki i BackgrouDRb to tutaj overkill (przynajmniej na tyle na ile opisałeś swój problem).

Jeśli faktycznie potrzebujesz czegoś co odpali długo działającą metodę po jakiejś akcji w Rails to jest jeszcze Spawn Najlepiej napisz co dokładnie próbujesz zrobić

Myślę, że BackgrounDRb będzie ok, ponieważ ma schedulera i co najważniejsze już zacząłem pisać.

//EDIT:

Zrobiłem :slight_smile: - Oczywiście dobre rozwiązanie jest zawsze najprostsze - skrypt uruchamiany przez script/runner, działa wspaniale (do tej pory).
Nie trzeba było żadnych obserwatorów, barckground workerów, spawnów, ani innego kombinowania. (tylko czemu ja zawsze muszę pchać się w najdłuższą drogę?)

Wielkie dzięki dla Was za poświęcony mi czas.

no a czemu by nie skorzystac z crona, fajny tutek z reilowa wstawka do crona jest jako najnowszy odcinekna railscast