2015-02-28 20 views
6

Mam aplikację rails, w której mam funkcję, która wysyła kilka e-maili. Chciałbym to zrobić asynchronously i myślałem, że metoda deliver_later to zrobi. Obecnie mam pewne opóźnienie, od kiedy użytkownik klika submit, dopóki formularz nie zostanie przesłany - co prowadzi do złego doświadczenia użytkownika (jest to dość prosta forma). Moja implementacja wygląda następująco:Rails 4 - Mailer nie działa tak, jak się spodziewam, blokuje UI

def create 

    respond_to do |format| 
    if @competition.save 
     [...] 
     send_notification_to_team_members 
    end 
end 

def send_notification_to_team_members 
    @team.members.each do |member| 
    unless member.user.eql?(current_user) 
     Mailer.deliver_new_competition_notification(member.user, @competition).deliver_later 
    end 
    end 
end 

Obecnie trwa około 4 sekundy, aby akcja została zakończona. Próbowałem również:

Mailer.deliver_new_competition_notification(member.user, @competition).deliver_later(wait: 1.minute) 

Następnie trwa jeszcze dłużej - Chciałbym oszacować ~ 1 minutę.

Czy używam błędnie deliver_later, czy też metoda nie działa zgodnie z oczekiwaniami. W takim razie, czy istnieje inna metoda, którą mogę wykorzystać, aby poprawić swoją wydajność?

+0

Z jakiego zaplecza aktywnie pracuję? –

+0

Asynchronicznie powinieneś wysyłać wiadomości e-mail, jeśli korzystasz z 4.2, możesz użyć ActiveJob, lub jeśli nie, powinieneś użyć takich rozwiązań jak Sidekiq lub Rescue –

+0

FYI: [Tutaj] (https: //blog.engineyard.com/2014/getting-started-with-active-job) jest dobrym artykułem o używaniu ActiveJob do wysyłania wiadomości e-mail –

Odpowiedz

14

deliver_later używa ActiveJob do wykonywania asynchronicznego wykonywania.

Jednak ActiveJob nie zapewnia samej asynchroniczności - jest to jednocząca warstwa api, którą może spełnić wiele backendów. Domyślnie po prostu uruchamia wszystko w linii, to nie jest asynchroniczne.

Aby uzyskać asynchroniczne użycie, należy wybrać asynchroniczny backend. Można skonfigurować backend w konfiguracji Twojej aplikacji

config.active_job.queue_adapter = ... 

Ogólnie większości adapterów wymagają odpowiedniego gem (np delayed_job, sidekiq, sucker_punch), które mogą mieć własne współzależności też (na przykład sidekiq wymaga użycia Redis.

+0

Dzięki! Zdecydowałem się zainstalować 'delayed_job', z:' gem 'delayed_job_active_record'', i poszedłem za procesem instalacji tutaj: https://github.com/collectiveidea/delayed_job_active_record. W 'application.rb' dodałem:' config.active_job.queue_adapter =: delayed_job'. Używam go w ten sposób: 'Mailer.deliver_new_competition_notification (member.user, @competition) .deliver_later!'. Nie dostaję żadnych błędów, ale e-maile nie są dostarczane - na 'localhost: 3000'. Czy coś przeoczyłem? – Anders

+0

@ Osoby, które muszą rozpocząć pracę z jednym lub więcej pracownikami z opóźnieniem –

+0

Dzięki, postanowiłem zamiast tego użyć 'sidekiq'. Wydaje się, że wyglądało to łatwiejsze do ustawienia. Ale natknąłem się na kilka innych problemów, zadałem nowe pytanie tutaj: http://stackoverflow.com/questions/28796293/rails-4-2-sidekiq-not-sending-emails-in-velopvelopment – Anders