Ruby on Rails 不断更新一个变量

Ruby on Rails constantly updating a variable

目前我正在构建一个应用程序,允许用户对产品出价并允许管理员批准它们。 'transactions' 本身发生在应用程序的范围之外。目前,用户在 transaction/new 页面上看到资产的价格,并通过提交表单来提交出价。管理员单击按钮批准出价。

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 并以这种方式使用价格。我研究了一些 运行ning 后台作业的技术,包括 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"

那个代码运行s。问题是我有点迷失了如何处理价格变量并将其从工作人员传回给用户。我看过 sidekiq 和 resque 的 Railscasts 剧集。我已经正确编写了排队和 运行 的后台工作人员和作业,但我不知道如何将它们实现到我的应用程序中。这是我第一次处理后台工作,所以我有很多东西要学。我花了一些时间研究这个问题,似乎更多的后台作业被用于更长的 运行ning 任务,比如更新数据库索引,而不是不断重复的作业(比如每 5 秒的 API 请求)。

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

我想在这种情况下你应该使用 rails 缓存。在你的控制器中放入类似这样的东西:

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

您还可以通过设置 expires_in 参数来配置缓存过期日期,请参阅 https://apidock.com/rails/ActiveSupport/Cache/Store/fetch 了解更多信息。

关于使用后台作业来更新您的 "price" 值,无论如何您都需要存储检索到的数据(使用某种数据库)并在您的控制器中获取它。

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

例如,我会用 reader 和编写器方法定义缓存,然后在必要时填充缓存:

  1. 有人在您的网站第一次加载产品"foo"
  2. Rails 检查缓存发现它是空的
  3. Rails调用外部服务
  4. Rails 使用其 writer 方法将外部服务响应保存到缓存
  5. Rails returns 对客户端的缓存响应

此后将由 Sidekiq 填充缓存:

  1. 有人在您的网站上 加载产品 "foo"
  2. Rails检查缓存,从上面找到缓存的值
  3. Rails 触发 Sidekiq 作业告诉它刷新缓存
  4. Rails returns 对客户端的缓存响应

从上面的第 3 步继续:

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

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

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