Twilio - 延迟工作,工作或工人或什么?

时间:2011-04-13 21:33:54

标签: ruby-on-rails-3 cron delayed-job

我正在构建一个使用Twilio的应用程序,我们需要在通话开始后的一段时间内调用Twilio的服务器。

我正在使用RoR,现在正在使用Heroku,但如果需要,我们可以将它移到别处。

我看过延迟工作和Cron工作,但我不知道应该知道应该走哪条路。

似乎延迟作业和cron作业通常会重复发生(时间不是很准确),并且不是通过用户操作而是以rake开头,对吗?

什么工具会让我对这个用例有一定的准确性?

1 个答案:

答案 0 :(得分:1)

Twilio Evangelist在这里。

我喜欢用Redis支持的工作队列来解决这个问题。 Redis是一个键值存储,我们可以使用Resque(发音为'rescue')和Resque-Scheduler来提供排队机制。例如,我们可以让应用程序通过使用Twilio REST API创建呼叫来响应用户交互。然后,我们可以将一个工作任务排队,该任务将在稍后的指定时间内对该调用执行某些操作。在这里,我只是在几秒钟之后得到呼叫的状态(而不是在呼叫完成时等待status callback)。

Heroku在使用Resque时有很好的演练,在Resque with Rails上也有一个很棒的Rails Casts episode。 Heroku提供了一个名为data add-onReddis Cloud来提供Redis服务器。虽然对于开发我在我的计算机上运行本地服务器。

我基于Heroku教程和Rails Casts剧集创建了一个简单的应用程序。它有一个控制器和一个模型。我在模型上使用callback来创建出站Twilio呼叫。这样,当创建新的Call记录时,我们会启动出站​​Twilio呼叫:

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

我正在使用关注点来启动呼叫,因为我可能希望从我的应用中的许多不同位置执行此操作:

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

这只是创建出站Twilio调用,并返回调用SID,以便我可以更新我的模型。

现在已拨打电话,所以我想查看其状态。但是,由于我们希望呼叫首先响铃,我们将在15秒内检查它。在我的控制器中,我使用Resque-Scheduler中的Resque.enqueue_in方法来管理我的时间:

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

这表示Resque在执行任务前等待15秒。它期望调用名为MessageWorker的Resque工作类,并将传递带参数的哈希:{:call => @call.id}。为确保按时发生这种情况,我将RESQUE_SCHEDULER_INTERVAL设置为0.1秒,因此非常精确。 MessageWorker本身非常简单,它找到调用记录并使用Call SID获取更新状态并将其保存到数据库中:

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

当我在本地运行时,我必须启动Redis服务器,Redis Worker rake任务,Redis Schedule rake任务,我使用Foreman和Unicorn来运行Rails应用程序。您可以将所有这些配置到Procfile中,以便在Heroku上运行。 tutorial on Heroku是进行此设置的绝佳演练。

但是现在我可以创建一个电话并让它拨打电话。与此同时,我可以刷新calls/show/:id页面,并在15秒后运行工作进程时看到神奇更新的值。

我还发现resque-web对于调试Resque非常有用,因为它可以很容易地看到你的任务发生了什么。

希望这有帮助!