flash error from delayed job in rails

960 Views Asked by At

In my rails app, I'm running delayed jobs with Sucker Punch gem. I'm looping through some phone numbers sending an sms message to each with Twilio.

If there is an error with Twilio sending it, I can capture it with a rescue just fine, but is there a way to notify the user without just raising an exception showing an error page?

Ideally, it would be as a flash message (or other notification) when it happens. Is there some way to do this?

1

There are 1 best solutions below

1
Richard Peck On BEST ANSWER

As mentioned in the chat by Nick Veys, the solution to this will be to create some sort of persistence with the data.

--

Push

I think the functionality you're looking for will be achieved by using some sort of "push" technology, notably Pusher. This will give you the ability to create a set of files / settings which will provide the ability for the message to appear for the user.

I would personally set up the following:

  1. DelayedJob processes requests as required
  2. If the message raised an error, store the error
  3. Send the error message to the user with the push implementation

So I would do this:

#Gemfile
gem 'aasm', '~> 3.3.3'
gem 'pusher', '~> 0.14.1'

#app/models/message.rb
class Message < ActiveRecord::Base
   include AASM

   aasm do
     state :queued, :initial => true
     state :sending
     state :delivered
     state :error

     event :sent do
       transitions :from => [:queued, :sending], :to => :sent
     end

     event :raise_error do
       transition :from => [:queued, :sending], :to => :error, :on_transition => Proc.new {|obj, *args| obj.set_message(*args) }
     end

     def set_message(message)
        self.update(error: message)
        Redis.lpush(self.user.id, self.id)
     end
   end

end

This means that if you attempt to send the message, you'll be able to update the message as follows:

@message = Message.find params[:id]
if [[message.send_error]]
    @message.raise_error(error.message)
end

This means that you'll then be able to append the messages into a Redis instance, which you can then cycle through with Pusher:

--

Pusher

The value of this will be that when you use a front-end notification service such as Pusher, what you're really doing is taking data from your application, and sending it via a websocket, or maybe SSE, to the front-end browser

This is really what you need -- the ability to display the message for the user as / when it happens. To do this, I would use the following:

#app/assets/javascripts/application.js
pusher = new Pusher("**************")

channel = pusher.subscribe("private-user-[[username]]")             
channel.bind "error", (data) ->
    alert data.message

This will give you the ability to process the Redis queue you made, allowing you to send the requested updates as they are made:

#app/workers/pusher.rb
class PusherQueue
   @queue = :pusher
   def self.perform(user, message)
       # push message here
   end
end

This connects with the Pusher service, allowing you to "listen" for the updates you'll receive from the server. This means that if you are able to populate these updates (error messages) using the above code, you'll be able to send the errors to the users as they interact with your app

You read up more about Pusher / push technologies here: