开发者

Twilio - delayed job, cron job, or worker or what?

I am building an app that is using Twilio and we need to call Twilio's server a certain period after the call starts.

I'm using RoR and right now its on Heroku, but we can move it elsewhere if need be.

I've looked at Delayed Jobs and Cron jobs but I don't know enough about it to know which route I should take.

Seems like Delayed jobs and cron jobs are usually reoccurring (not very accurate with timing) and are started with rake not by a user action, right?

What tool will give me minute accuracy开发者_如何学编程 for this use case?


Twilio Evangelist here.

I like to approach this with Redis backed worker queues. Redis is a key-value store, which we can use with Resque (pronounced 'rescue'), and Resque-Scheduler to provide a queueing mechanism. For example, we can have the application respond to user interaction by creating a call using the Twilio REST API. Then we can queue a worker task that will do something with the call a specified amount of time later. Here, I'm just going to get the status of the call after a few seconds (instead of waiting for the status callback when the call completes).

Heroku have a really good walkthrough on using Resque, there is also an excellent Rails Casts episode on Resque with Rails. A data add-on is available from Heroku called Reddis Cloud to provide a Redis server. Although for development I run a local server on my computer.

I've created a simple app based on the Heroku tutorial and the Rails Casts episode. It has a single controller and a single model. I'm using a callback on the model to create an outbound Twilio call. Such that when a new Call record is created, we initiate the outbound Twilio call:

class Call < ActiveRecord::Base
  # Twilio functionality is in a concern...
  include TwilioDialable

  after_create do |call|
    call.call_sid = initiate_outbound call.to, 
                                      call.from,
                                      "http://example.com/controller/action"
    call.save
    call
  end 
end

I'm using a concern to initiate the call, as I may want to do that from many different places in my app:

module TwilioDialable
  extend ActiveSupport::Concern

  include Twilio::REST
  def initiate_outbound to, from, url 
    client = Twilio::REST::Client.new ENV['TW_SID'], ENV['TW_TOKEN']
    client.account.calls.create(to: to, from: from, url: url).sid
  end 
end

This simply creates the outbound Twilio call, and returns the call SID so I can update my model.

Now that the call has been placed, so I want to check on its status. But as we want the call to ring a little first, we'll check it in 15 seconds. In my controller I use the Resque.enqueue_in method from Resque-Scheduler to manage the timing for me:

Resque.enqueue_in(15.seconds, MessageWorker, :call => @call.id)

This is instructing Resque to wait 15 seconds before performing the task. It is expecting to call a Resque worker class called MessageWorker, and will pass a hash with the parameters: {:call => @call.id}. To make sure this happens on time, I set the RESQUE_SCHEDULER_INTERVAL to 0.1 seconds, so it will be very precise. The MessageWorker itself is fairly simple, it finds the call record and uses the Call SID to get the updated status and save this to the database:

class MessageWorker
  @queue = :message_queue
  def self.perform params
    # Get the call ID to do some work with...
    call = Call.find(params["call"])
    # Setup a Twilio Client Helper with credentials form the Environment...
    client = Twilio::REST::Client.new ENV['TW_SID'], ENV['TW_TOKEN']

    # We could get some 
    status = client.account.calls.get(call.call_sid).status
    # Update my call object.
    call.status = status
  end 
end

When I ran this locally, I had to start the Redis server, the Redis Worker rake task, the Redis Schedule rake task, and I am using Foreman and Unicorn to run the Rails app. You can configure all of this into your Procfile for running on Heroku. The tutorial on Heroku is a great walkthrough for setting this up.

But now I can create a call and have it dial out to a phone. In the mean time I can refresh the calls/show/:id page and see the value magically updated when the worker process is run 15 seconds later.

I also find that resque-web is really useful for debugging Resque, as it makes it really easy to see what is happening with your tasks.

Hope this helps!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜