Odpalanie delayed_job razem z serverem

Problem jest następujący:
W portalu są operacje, które operują na dużych plikach excela i csv. Zadania te odpalane są za pomocą delayed_job:

price_set.send_later :import

Wszystko działa git nie licząc samego odpalania procesu delayed_job. Logicznym byłoby odpalać proces razem z serverem gdzieś w init-cie, ale powoduje to zapętlenie serwera, bo każdy z 2 sposobów odpalenia tasków (rake jobs:work i ruby script/delayed_job start) powoduje inicjację serwera i odpala nieskończoną liczbę procesów. Można ewentualnie “z palca” odpalić proces na serwerze, ale najwyraźniej proces taki ginie razem z końcem sesji (druga sprawa, że to trochę niezbyt dobry pomysł). Kolejna opcja to capistrano razem z poniższym skryptem:

[code]after “deploy:stop”, “delayed_job:stop”
after “deploy:start”, “delayed_job:start”
after “deploy:restart”, “delayed_job:restart”

namespace :deploy do
desc “Restarting mod_rails with restart.txt”
task :restart, :roles => :app, :except => { :no_release => true } do
run “touch #{current_path}/tmp/restart.txt”
end
end

namespace :delayed_job do
desc “Stop the delayed_job process”
task :stop, :roles => :app do
run “cd #{current_path}; RAILS_ENV=production script/delayed_job stop”
end

desc “Start the delayed_job process”
task :start, :roles => :app do
run “cd #{current_path}; RAILS_ENV=production script/delayed_job start”
end

desc “Restart the delayed_job process”
task :restart, :roles => :app do
run “cd #{current_path}; RAILS_ENV=production script/delayed_job restart”
end
end[/code]
Powyższe rozwiązanie jednak działa nadal dość tymczasowo i proces ginie.
Aha, muszę dodać że konfiguracja serwera to Apache + Phusion Passenger.

Kolejna możliwość to dodać bluepill do startowania delayed_job:

[code]#deploy.rb
after “deploy:restart”, “bluepill:quit”, “bluepill:start”
namespace :bluepill do
desc “Stop processes that bluepill is monitoring and quit bluepill”
task :quit, :roles => [:app] do
sudo “bluepill stop”
sudo “bluepill quit”
end

desc “Load bluepill configuration and start it”
task :start, :roles => [:app] do
sudo “bluepill load /home/www/app/current/config/production.pill”
end

desc “Prints bluepills monitored processes statuses”
task :status, :roles => [:app] do
sudo “bluepill status”
end
end

#production.pill
Bluepill.application(“app”) do |app|
app.process(“delayed_job”) do |process|

process.start_command = "/home/www/app/current/script/delayed_job start RAILS_ENV=production"
process.pid_file = "/home/www/app/current/tmp/pids/delayed_job.pid"
process.stop_command  = "/home/www/app/current/script/delayed_job stop RAILS_ENV=production"
process.uid = "deploy"
process.gid = "deploy"

end
end[/code]
Co zrobić, żeby to zaczeło działać jak powinno?

w linuxie zeby proces nie ginał musisz go wysłać w tło, czyli odpalić jako demon, skorzystać z screen’a …

wtedy jako parent nie jest wirtualny terminal, a proces z PID 1 czyli INIT
inaczej jak zabijasz parenta to zabijasz wszystko co on odpalił.

No ale to wiedza juz z systemów operacyjnych.

pewnie można to zrobić jakoś bardziej rails a nie linux way ;]

wieć sprawdź czy nie ma opcji -d

czyli zrób mi demona ;]

Nie wiem w czym problem. Odpalenie delayed_job powoduje wystartowanie procesu w tle, bez podawania dodatkowych opcji. Może jakiś błąd powoduje zatrzymanie demona DJa? (sprawdź logi)

God jest przydatny przydatny do monitorowania i uruchamiania procesów: http://god.rubyforge.org/ Używamy tego w jednym projekcie właśnie do pilnowania, czy delayed_job działa.

Wspomniany przez Martin_wroc bluepill wygląda na lepszy od goda jeśli idzie o użycie pamięci.

W jednym z naszych starszych projektów użyliśmy goda i skończyło się to zarżnięciem maszyny. God ma straszne wycieki pamięci :frowning:

Jakoś przegapiłem bluepill. Nie zauważyliśmy u nas wycieków pamięci, ale będziemy uważać, bo bluepill wygląda na równie przyjemny w używaniu.

A używasz może też thinking-sphinx? Bo jeżeli tak, to thinking-sphinx ma wbudowaną własną wersję delayed_job. Ja miałem też z tym problem. Pomogła aktualizacja ts no i samego delayed_job.

Logi wyglądają ok. Wszystkie taski jak już się odpalą to przechodzą. Problemem jest tylko utrzymanie ich w działaniu. God faktycznie ma duże leaki w pamięci więc Bluepill wydaje się lepszy.
Problem rozwiązał się sam. Nie wiem jak, bo po prostu wszystko zaczęło nagle działać i od niedzieli w nocy wszsytko jest ok. Dzięki za pomoc.

Używam forka delayed_job zrobionego przez Collectiveidea, http://github.com/collectiveidea/delayed_job, gdzie najlepiej wrzucić tą linijkę dla aplikacji produkcyjnej.
RAILS_ENV=production script/delayed_job start
Może dodać delayed_job do bluepill http://github.com/arya/bluepill jak opisano w tym tutorialu http://rails.co.za/2009/11/14/monitoring-delayed-job-with-bluepill.html tylko jak odpalac wtedy samego bluepilla ?
? Czy to normalne ze deamon delayed_job’a zajmuje 30mb pamięci ?

Ja używam capistrano i w nim mam taski do odpalania bluepill. Problem pojawia się po restarcie serwera bo wtedy podnosi się sam serwer aplikacji, a nie capistrano. Można zawsze dodać jakieś zadanie które startuje razem z systemem. Deamon dj zajmuje dużo bo odpala sobie instancję serwera, dzięki czemu pracuje w kontekście aplikacji i ma dostęp do ActiveRecord.
http://blog.plataformatec.com.br/2010/02/monitoring-delayed-job-with-bluepill-and-capistrano/

Pytanko apropo delayed_job. Mam zmianę hasła, po zatwierdzeniu dodaje nowe zadanie które ma wysłac hasło użytkownikowi. Metoda w kontrolerze wyglada tak:

[code=ruby] def update

@user.password = params[:user][:password]
@user.password_confirmation = params[:user][:password_confirmation]

if @user.save
  @user.deliver_password_changed!
  flash[:notice] = I18n.t("password_resets.success")
  redirect_to root_url
else
  flash.now[:notice] = I18n.t("password_resets.fail")
  render :action => :edit
end

end[/code]
następnie w modelu User

def deliver_password_changed! Notifier.send_later :deliver_password_changed, self end
i w Notifier:

def password_changed(user) setup_email user.email subject I18n.translate("notifier.password_changed_title") body :user => user end
Email spoko się wysyła po odpaleniu rake jobs:work, niestety zmienna user.password w widoku emaila jest nil i nijak nie idzie załączyć ustawionego hasła. Aha, do autentyfikacji używam Authlogica, czyli w bazie oczywiście nie ma pola password, jest tylko pole z zakodowanym. Podejrzewam że dzieje się tak dlatego ponieważ delayed_job nie zapamiętuje obiektu user samego w sobie tylko referencje w bazie do rekordu user i metody którą ma na nim wywołać? Jak to obejść ? Czy można jakoś do delayed_job przekazać zmienną z hasłem, o ile to bezpieczne trzymać tam niezakodowane hasło przez chwilę. A może poprostu zrezygnować z delayed_job w tym przypadku ?

Po prostu nie wysyłaj hasła e-mailem. Serio. A co jak ktoś przechwyci pocztę?

hmm, też jest to jakaś opcja