简体   繁体   English

使用Resque / Rails保持工作结果

[英]Persist job results with Resque / Rails

In my Rails app, I'm trying to take my working API calls and have them handled by background workers. 在我的Rails应用程序中,我试图进行有效的API调用,并由后台工作人员处理它们。

I have the following in app/jobs/api_request_job.rb: 我在app / jobs / api_request_job.rb中具有以下内容:

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

The Query class is where the HTTParty requests are being executed (there are lots of methods for different query types with the same basic format as the parks method: 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

And, finally, the controller. 最后是控制器。 Before trying to farm this action out to background workers, this line was working fine: @results = Query.new(params).start 在尝试将此操作提供给后台工作人员之前,此行工作正常: @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

I'm running redis, have resque installed, and am running the task/starting the workers. 我正在运行Redis,已安装resque,并正在运行任务/启动工作程序。 The current value being returned for @results is true instead of the hash of results I was need to get back. @results返回的当前值是true而不是需要返回的结果的哈希值。 Is there a way to have the results of the Resque job persist and return data instead of true ? 有没有办法使Resque作业的结果持久存在并返回数据而不是true What am I missing about how to get background workers to return the same type of data my regular api calls were returning? 对于如何让后台工作人员返回我的常规api调用返回的相同类型的数据,我丢失了什么?

Many thanks in advance! 提前谢谢了!

The true you are receiving means the job was scheduled enqueued successfully. 您所收到的true表示该作业已成功排定入队。 The worker will pick it up and run it on the background asynchronously, which means, not at same time as the thread that enqueued it. 工作程序将拾起它并在后台异步运行它,这意味着,与排队它的线程不同。 So there's no way to retrieve the returned value from the job. 因此,无法从作业中检索返回的值。

If you need the value from that process, you have to run it from the controller without the worker. 如果需要该过程中的值,则必须在没有工作程序的情况下从控制器运行它。 Also, you wouldn't gain anything from just pushing the work to be done by another process as the web process would have to wait for the response to then keep going anyway. 而且,仅将工作推到另一个进程来完成,您将不会获得任何收益,因为Web进程将不得不等待响应然后继续进行。

If you need that returned value right away and are doing this for performance reasons, then you could look into other forms of concurrency, like having another thread doing the request and then only grabbing the result when you need it on the view like: 如果您需要立即返回的值,并且出于性能原因正在执行此操作,那么您可以考虑其他形式的并发,例如让另一个线程来处理请求,然后仅在需要时在视图中获取结果,例如:

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

  def value
    @thr.join
  end
end

on the controller 在控制器上

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

and on the view 并在视图上

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

but you'd still have to work around error handling which can get pretty complicated, but is doable. 但是您仍然必须解决可能会变得非常复杂但可行的错误处理。

Personally, I'd just make the request in place, but you know your domain better than me. 就个人而言,我只是将请求发送到位,但是您比我更了解您的域名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM