Ruby on Rails不断更新变量

时间:2017-11-21 17:50:55

标签: ruby-on-rails ruby sidekiq delayed-job resque

目前我正在构建一个应用程序,允许用户对产品和管理员进行出价以批准它们。 “交易”本身发生在申请范围之外。目前,用户在交易/新页面上查看资产的价格,并通过提交表单提交出价。管理员点击按钮批准出价。

class TransactionsController < ApplicationController
before_action :get_price

  def new
    @price = get_price
    @tansaction = Transaction.new
  end

  ###

  def get_price
    @price = <<Some External Query>>
  end

  def approve
    t = Transaction.find(params[:id])
    t.status = "Approved"
    t.update!
  end

显然这并不理想。每次用户想要提交出价时,我都不想查询API。理想情况下,我可以在后台每隔5-10秒查询一次这个API并以这种方式使用价格。我已经研究了几种运行后台作业的技术,包括delayed_job,sidekiq和resque。例如在sidekiq我可以运行这样的东西:

  #app/workers/price_worker.rb
  class PriceWorker
    include Sidekiq::Worker

    def perform(*args)
      get_price
    end

    def get_price
        @price = <<Some External Query>>
      end
  end

  #config/initializers/sidekiq.rb
  schedule_file = "config/schedule.yml"

  if File.exists?(schedule_file) && Sidekiq.server?
    Sidekiq::Cron::Job.load_from_hash YAML.load_file(schedule_file)
  end


  #config/schedule.yml
  my_price_job:
    cron: "*/10 * * * * * "
    class: "PriceWorker"

该代码运行。问题是我对如何处理价格变量并将其从工人传递给用户感到很遗憾。我观看过sidekiq和resque的Railscasts剧集。我编写了后台工作人员和排队并正常运行的作业,但我无法弄清楚如何将它们应用到我的应用程序中。这是我第一次处理后台工作,所以我有很多东西需要学习。我花了一些时间来研究这个问题,似乎更多后台作业用于更长时间运行的任务,例如更新数据库索引而不是不断重复的作业(比如每5秒一次API请求)。

总而言之,运行不断重复的任务(例如在Rails中查询外部API)的正确技术是什么?任何有关如何正确执行此操作的反馈将不胜感激!谢谢。

2 个答案:

答案 0 :(得分:0)

我想在这种情况下你应该使用rails cache。把这样的东西放在你的控制器中:

@price = Rails.cache.fetch('price') do
  <<Some external query>>
end

您还可以通过设置expires_in参数来配置缓存过期日期,有关详细信息,请参阅https://apidock.com/rails/ActiveSupport/Cache/Store/fetch

关于使用后台作业来更新您的&#34;价格&#34;值,你需要存储检索到的数据(使用某种数据库)并在你的控制器中获取它。

答案 1 :(得分:0)

这不是后台工作的工作方式。你是对的,你有很多阅读要做。考虑运行像Sidekiq这样的异步作业处理器作为运行完全独立的应用程序。它与您的Rails应用程序共享相同的代码库,但它完全单独运行 。如果您希望这两个独立的应用程序相互通信,那么必须设计和编写该代码。

例如,我将使用reader和writer方法定义缓存,然后在必要时填充缓存:

  1. 有人为您网站上的第一次时间加载产品“foo”
  2. Rails检查缓存并发现它为空
  3. Rails调用外部服务
  4. Rails使用其编写器方法
  5. 将外部服务响应保存到缓存中
  6. Rails将缓存的响应返回给客户端
  7. 此后,Sidekiq将填充缓存:

    1. 有人在您网站第二次时加载产品“foo”
    2. Rails检查缓存并从上面找到缓存的值
    3. Rails激活Sidekiq作业,告诉它刷新缓存
    4. Rails将缓存的响应返回给客户端
    5. 继续上述第3步:

      1. Sidekiq检查上次刷新缓存的时间,如果超过 x 秒,则继续,否则退出
      2. Sidekiq调用外部服务
      3. Sidekiq使用其编写方法
      4. 将外部服务响应保存到缓存

        下一个客户端加载产品“foo”时,Rails将读取Sidekiq更新(或未更新)的缓存。

        对于这种类型的系统,缓存必须是某种外部存储,如关系数据库(MySQL,Postgres,Sqlite)或NoSQL数据库(Redis,memcache)。您不能使用内部Rails缓存,因为Rails缓存仅存在于Rails应用程序的内存空间内,并且Sidekiq 可读。 (因为Sidekiq是一个完全独立的应用程序)