Wiele procesów i reload backendu i18n

Piszę backend do i18n korzystajacy z baz danych i chce go restartować wraz z pojawieniem się w bazie nowych tłumaczeń. Najłatwiej to zrobić po prostu wywołując reload w after_save. Sprawa się ponoć komplikuje, gdy nasza aplikacja działa na kilku procesach. Wtedy backend restartowany jest tylko na procesie w którym następuje zapis, a reszta dalej chodzi na starych danych, Aby to ominąć mogę za każdym razem, przy każdym requeście, pytać bazę o to czy są nowe wpisy w niej i wtedy backend we wszystkich procesach się przeładuje. Ale chciałbym to zrobić bez konieczności tych nieustannych zapytań do bazy, czy jest coś nowego. Najlepiej byłoby gdyby był jakiś sposób do zrestartowania backendu na wszystkich procesach, ale w tej kwestii jestem kompletnym laikiem i nie bardzo wydaje mi się to możliwe. Mam nadzieję że jednak jest inaczej i da radę to jakoś ładnie zrobić. Ktoś ma jakieś sugestie?

Zapewne będzie to trudne do wykonania, ale z całą pewnością jest to dość mocno związane ze sposobem uruchamiania aplikacji (wiele procesów mongrela? Passenger?).

Jak narazie, mam dwa pomysly, ale nie za piekne.

Proces ktory zmienia cos w translacjach, tworzy plik, np. tmp/reload_translations, kazdy proces trzyma czas utworzenia tego pliku, przy kazdym requescie, proces sprawdza czy czas utworzenia pliku nie jest “wiekszy” od czasu ktory trzyma w zmiennej, jesli tak to przeladowuje translacje i aktualizuje sobie czas utworzenia pliku.

Mozna by tez zrobic tak, ze proces ktory cos zmienia, tworzy sobie watek, i w nim odpala url, dla kazdego procesu thina(czy czegos tam), np. localhost:8000/translations/reload, ale jesli thin chodzi na socketach unixowych to nie wiem za bardzo jaki url wywolac.

//Edit

Chociarz, zrobienie tego samego co opisalem dla plikow, z uzyciem bazy, wydaje mi sie czystsze. Jeden select na pobranie wersji aktualnej translacji wydaje sie byc OK.

Jeśli korzystasz z Passengera to restart wszystkich procesów najłatwiej zrobić tworząc pusty plik tmp/restart.txt (np. po zmianie w bazie)

A w jakim celu chcesz go restartować? Odświeżenia cache? Jeśli tak, to dlaczego nie możesz skorzystać z gotowych mechanizmów cache?

Widzę jeszcze możliwe 2 rozwiązania:

  1. Jeśli masz możliwość skorzystania z memcache to umieść w nim zmienną z datą. Tą zmienną będą widzieć wszystkie procesy - na podstawie daty ostatniej aktualizacji konkretny proces będzie mógł przeładować backend.

  2. Użyj Unicorn (http://unicorn.bogomips.org/) jako serwera rails. Każdy worker restartuje się co pewien odcinek czasu (standardowo 60 sekund) - otrzymasz porządany efekt z lekkim opóźnieniem.

To ma być uniwersalny gem, który ma działać wszędzie gdzie się tylko da, więc wpływu na to jak i na czym jest uruchomiona aplikacja nie mam żadnego. Więc chyba w tej sytuacji nie uda się znaleźć żadnego smart sposobu.

Odpytywanie co request pliku jest równie mało ciekawe i zadowalające, niż pytanie bazy. Prawdę mówiąc wolę już pytać bazę

Chce go restartować po to, aby właśnie wyczyścić cache, po to aby mogły do niego wskakiwać aktualne wersje tłumaczeń. I tutaj korzystam ze standardowego mechanizmu cacheowanie dla I18n::Backend::Simple, po którym dziedzicze. Całość działa tak, że jak nie mam czegoś w cache’u, to szukam w bazie. Nie muszę wtedy reloadować backendu gdy mam nowe wpisy, bo one same wskoczą do cache’a, ale gdy już mam jakąś edycją istniejącego tłumaczenia to muszę już ten reload zrobić.

[quote=Piotr Misiurek]Odpytywanie co request pliku jest równie mało ciekawe i zadowalające, niż pytanie bazy. Prawdę mówiąc wolę już pytać bazę

Chce go restartować po to, aby właśnie wyczyścić cache, po to aby mogły do niego wskakiwać aktualne wersje tłumaczeń.[/quote]
Obawiam się, że w tej sytuacji jedyne co możesz zrobić skutecznie to per-request sprawdzać datę ostatniej aktualizacji tłumaczeń i ręcznie czyścić cały cache jeśli nie jest świerzy.

Oznacza to, że podczas pracy tłumacza cache tłumaczeń będzie wygasany dość często co zaowocuje nieco powolnymi requestami (dużo tłumaczeń do wciągnięcia po wygaśnięciu cache). Z drugiej jednak strony będziesz mógł zagwarantować aktualną zawartość strony i pełną niezależność od użytego serwera. Jedno query do db to niewielki koszt w takim wypadku.

Następnym krokiem w implementacji jest optymalizacja wyciągania danych do cache. Może warto to robić tylko raz i ryzykować pojedynczym wolnym requestem (wyciągnięcie Translation.all…) i wrzucić całość do Rails.cache?