使用Resque / Rails保持作业结果

时间:2014-12-02 02:43:17

标签: ruby-on-rails redis backgroundworker resque

在我的Rails应用程序中,我正在尝试接受我的API调用,并由后台工作人员处理。

我在app / jobs / api_request_job.rb中有以下内容:

class ApiRequestJob
  def self.perform(params)
    Query.new(params).start   
  end
end

Query类是执行HTTParty请求的地方(对于具有与parks方法相同的基本格式的不同查询类型,有许多方法:

require 'ostruct'

class Query
  include FourSquare

  attr_reader   :results,
                :first_address,
                :second_address,
                :queries, 
                :radius

  def initialize(params)
    @results        = OpenStruct.new
    @queries        = params["query"]
    @first_address  = params["first_address"]
    @second_address = params["second_address"] 
    @radius         = params["radius"].to_f 
  end

  def start
    queries.keys.each do |query|
      results[query] = self.send(query)
    end
    results
  end

def parks
  category_id = "4bf58dd8d48988d163941735"
  first_address_results = FourSquare.send_request(@first_address, radius_to_meters, category_id)["response"]["venues"]
  second_address_results = FourSquare.send_request(@second_address, radius_to_meters, category_id)["response"]["venues"]
  response = [first_address_results, second_address_results]
end

最后,控制器。在尝试将此操作提供给后台工作人员之前,此行正常运行:@results = Query.new(params).start

class ComparisonsController < ApplicationController
  attr_reader :first_address, :second_address

  def new
  end

  def show
    @first_address = Address.new(params["first_address"])
    @second_address = Address.new(params["second_address"])
    if @first_address.invalid?
      flash[:notice] = @first_address.errors.full_messages
      redirect_to :back    
    elsif Query.new(params).queries.nil? 
      flash[:notice] = "You must choose at least one criteria for your comparison."
      redirect_to comparisons_new_path(request.params)
    else
      @queries = params["query"].keys
      @results = Resque.enqueue(ApiRequestJob, params)  # <-- this is where I'm stuck
    end
  end

end

我正在运行redis,安装了resque,并且正在运行任务/启动工作人员。 @results返回的当前值是true,而不是我需要返回的结果的哈希值。有没有办法让Resque作业的结果保持不变并返回数据而不是true?关于如何让后台工作人员返回我的常规api调用返回的相同类型的数据,我错过了什么?

非常感谢提前!

1 个答案:

答案 0 :(得分:1)

您收到的true表示该作业已安排成功排队。工作人员会将其拾取并在后台异步运行,这意味着,不会与排队的线程同时运行。因此,无法从作业中检索返回的值。

如果您需要该进程的值,则必须在没有worker的情况下从控制器运行它。此外,你不会从另一个过程推动工作中获得任何收益,因为网络流程必须等待响应,然后继续前进。

如果您需要立即返回值,并且出于性能原因这样做,那么您可以查看其他形式的并发,例如让另一个thread执行请求,然后只在需要时抓取结果在视图上:

class AsyncValue
  def initialize(&block)
    @thr = Thread.new(&block)
  end

  def value
    @thr.join
  end
end

在控制器上

@results = AsyncValue.new { Query.new(params).start  }

并在视图上

<%= @results.value.each .... %>

但是您仍然需要解决错误处理问题,这可能会非常复杂,但是可行。

就个人而言,我只是提出了请求,但您比我更了解您的域名。