2016-08-03 7 views
1

In einem meiner Rails-Anwendung-Controller zu verbinden, kann ich so etwas wie diese:deliver_later mit Sidekiq verursacht 500 Fehler, wenn nicht in der Lage zu Redis

def create 
    @user = User.create(user_params) 

    # send welcome email 
    UserMailer.welcome(@user).deliver_later 
end 

Jetzt habe ich absichtlich so meinen Redis Server deaktiviert, dass ich kann, replizieren, was passieren würde, wenn eine Verbindung nicht über meine App hergestellt werden könnte.

Leider schlägt diese gesamte create Anfrage mit einem 500 fehl, wenn die deliver_later Verbindung zu Redis nicht herstellen kann.

Was ich möchte ist, dass die Anfrage immer noch erfolgreich ist, aber der Mailer schlägt lautlos.

Wie kann ich das erreichen?

Zusätzliche Informationen:

In config/initializers/action_mailer.rb:

rescue_from(Redis::CannotConnectError) do |exception| 
     Rails.logger.error "Original record not found: #{@serialized_arguments.join(', ')}" 
    end 

Dies wird allerdings nie auf Ausnahme genannt. Ich versuchte rescue_from(StandardError) und (Exception), aber das wurde auch nie genannt.

Ich verwende sidekiq als mein Job-Queue-Adapter:

config.active_job.queue_adapter = :sidekiq 

Der 500-Fehler ich erhalte, ist:

Redis::CannotConnectError (Error connecting to Redis on localhost:6379 (Errno::ECONNREFUSED)): 

Mein UserMailer eine Unterklasse von ApplicationMailer ist, die eine Unterklasse von ActionMailer::Base ist.

+0

Warum Sie nicht einfach die Ausnahme retten? – user3033467

+1

@ user3033467 wo? Ich habe den Code deliver_later überall in der App, also möchte ich es von einem einzigen Ort aus tun. – Snowman

+0

Ich kenne keine Möglichkeit, diesen Fehler global zu erfassen, ohne eine Fassade anzupassen oder einzuführen. –

Antwort

0

Um Anrufe zu deliver_later vor einem Absturz zu verhindern, wenn Redis unten ist, haben wir den folgenden Affen Patch:

# If +raise_delivery_errors+ is false, errors occurring while attempting to 
# enqueue the email for delivery will be ignored (for instance, if Redis is 
# unreachable). In these cases, the email will never be delivered. 
module MessageDeliveryWithSilentQueueingErrors 
    def deliver_later 
    super 
    rescue Redis::CannotConnectError => e 
    raise if raise_delivery_errors 
    # Log details of the failed email here 
    end 

    def deliver_later! 
    super 
    rescue Redis::CannotConnectError => e 
    raise if raise_delivery_errors 
    # Log details of the failed email here 
    end 
end 

ActionMailer::MessageDelivery.send(:prepend, MessageDeliveryWithSilentQueueingErrors) 
Verwandte Themen