在ActiveJob和Controller之间共享数据

时间:2015-06-01 10:23:15

标签: ruby-on-rails ruby-on-rails-4 ruby-on-rails-4.2 rails-activejob

每隔n秒,应用程序就会请求一个远程JSON文件,该文件为交易系统中的证券提供实时价格。 JSON有一个包含我需要的数据的块(marketdata)和一个包含当前dataversionversionseqnum)的块。

现在我使用ActionController::Live(在客户端使用EventSource)将更新的数据推送到浏览器。所有操作都在一种方法中完成:

  1. 打开SSE连接;
  2. 形成动态网址;
  3. 从远程服务器提取新数据;
  4. 比较/重新分配seqnum值;
  5. 根据需要更新数据库。
  6. 所以我现在的目标是将拉动和拉动分开。通过将更新的值推送到浏览器(ActiveJob)来更新数据库(ActionController::Live)。要做到这一点,我需要:

    • 要么存储在服务器端的某个地方seqnum& version在控制器和后台作业之间共享;
    • 或监控数据库以查找updated_at字段中的最新更改。

    基本上我有两个问题:

    • 上述两个选项之间的效率更高?还有其他好方法吗?
    • (如果第一个人有权存在)如何实施这种方法?

1 个答案:

答案 0 :(得分:3)

考虑到你可能会运行多个rails进程,我相信你很难让activejob以某种方式直接与rails控制器对话。

Defintely store seqnumversion,在任何情况下我都不会依赖updated_at,它很容易随机更新,所以最终没有任何实际原因将内容发送给客户。同样在这种情况下,如果文件已更新,它们似乎是非常可靠的字段。

使用投票

话虽如此,你想要"发出信号" ActionController::Live在某种程度上我害怕在这里进行投票是你唯一的选择,除非你的客户端有一个特定的时刻,它需要知道文件是否已经更新,在这种情况下你可能想要使用websockets或类似的东西。

所以,像

cached_request = YourCachedRequest.latest # Assuming it returns a single record
updated        = true
loop do
  if updated
    updated = false
    response.stream.write cached_request.serialize_in_some_way
  end
  current_version = cached_request.version # use seqnum too if you need
  cached_request = cached_request.reload
  updated = true if cached_request.version > current_version
  sleep 20.0
end

不进行投票

如果您想要一个不涉及轮询的选项,您只能选择我认为的websockets。但是,您有一个更有效的选择:

创建一个迷你应用程序(evenmachine / sinatra / something light),客户端将在其中进行轮询(您可以通过主应用程序将其分发到此迷你应用程序的不同节点),此应用程序的重点仅在于重新路由消息从您的主要应用程序到投票客户。

现在,您可以为主应用程序创建一个仅由延迟作业使用的内部API端点。仅当延迟作业注意到所获取的JSON相对于当前存储的JSON实际更新时,才会触发此终结点。如果是这种情况,它将会触及您的主应用API端点,而后者又会向您的所有迷你应用实例发送消息(可能再次,可能是通过HTTP API端点,这次是在您的迷你应用上)转向将它们发送给您的客户。

通过这种方式,您不会使主服务器过载,但只有这些小节点可能会出现本地化中断(这是一个很大的优势,而不是大系统中断)

相关问题