【问题标题】:Persist job results with Resque / Rails使用 Resque / Rails 保存作业结果
【发布时间】:2015-01-30 04:53:35
【问题描述】:

在我的 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 调用返回的相同类型的数据,我缺少什么?

非常感谢!

【问题讨论】:

  • 您好,您的问题解决了吗?

标签: ruby-on-rails redis backgroundworker resque


【解决方案1】:

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

如果您需要来自该进程的值,则必须在没有工人的情况下从控制器运行它。此外,仅将工作推给另一个进程完成,您不会有任何收获,因为 Web 进程必须等待响应才能继续运行。

如果您立即需要该返回值并且出于性能原因这样做,那么您可以研究其他形式的并发,例如让另一个 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 .... %>

但您仍然需要解决可能会变得非常复杂但可行的错误处理。

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

【讨论】:

  • 感谢您的回复!是的,我和其他一些人讨论过这个问题,并意识到后台工作人员不会帮助我提高性能,因为我的页面依赖于返回值。我喜欢线程建议,但我认为我最终会尝试通过抓取并将我支持的结果存储在数据库中来减少对 API 响应的依赖。
猜你喜欢
  • 2015-09-17
  • 1970-01-01
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 1970-01-01
  • 2016-08-03
相关资源
最近更新 更多