Sidekiq 应该如何在作业完成时在网页上通知用户?
How should Sidekiq notify user on the web page when job is finished?
用户可以通过由控制器操作处理的 Web 界面在我的系统中上传多个文件。
def import
paths = params[:files].map(&:path) if params[:files].present?
if paths
@results = MyRecord.create_from paths
end
redirect_to confirmation_my_records_path
end
class MyRecord < ActiveRecord::Base
def self.create_from(paths)
paths.each do |path|
MyRecordWorker.perform path
end
end
end
works/my_record_worker.rb
class MyRecordWorker
include Sidekiq::Worker
def perform(path)
# each time this is run, it is no I/O, just expensive math calculations that take minutes
collection = ExpensiveOperation.new(path).run
if collection && collection.any?
save_records(collection)
else
[]
end
end
end
因为 sidekiq 作业会在后台 运行,我如何通过确认页面通知用户作业已完成?我们不知道作业何时完成,因此 Rails 请求和响应周期在加载确认页面时无法确定任何内容。确认页面是否应该只说 "Processing..." 然后让 Faye 在作业完成后更新页面?
在您的应用程序中添加一个 RecordJobs
模型,用于存储谁上传了记录、记录数、上传时间等。
每次有人上传新记录时创建一个新的 record_job
并将其 id
传递给工作人员。工作人员可以更新该实例以指示其进度。
同时,应用程序可以查询现有的 record_job
并显示其进度。这可以在用户重新加载页面时通过主动轮询或网络套接字(取决于您的需要)来完成。
使用 ActionCable,这里是带有 Report 通道的示例
在routes.rb中添加以下行
mount ActionCable.server => '/cable'
使用以下代码在 app/channels 中创建一个 ReportChannel.rb
class ReportChannel < ApplicationCable::Channel
def subscribed
stream_from "report_#{current_user.id}"
end
end
使用以下代码在 app/assets/javascripts/channels 中创建 reports.coffee
window.App.Channels ||= {}
window.App.Channels.Report ||= {}
window.App.Channels.Report.subscribe = ->
App.report = App.cable.subscriptions.create "ReportChannel",
connected: ->
console.log('connected ')
disconnected: ->
console.log('diconnected ')
received: (data) ->
console.log('returned ')
data = $.parseJSON(data)
#write your code here to update or notify user#
并在作业末尾添加以下行
ActionCable.server.broadcast("*report_*#{current_user_id}", data_in_json_format)
用您的特定型号替换报告
看起来很简单吧:)
用户可以通过由控制器操作处理的 Web 界面在我的系统中上传多个文件。
def import
paths = params[:files].map(&:path) if params[:files].present?
if paths
@results = MyRecord.create_from paths
end
redirect_to confirmation_my_records_path
end
class MyRecord < ActiveRecord::Base
def self.create_from(paths)
paths.each do |path|
MyRecordWorker.perform path
end
end
end
works/my_record_worker.rb
class MyRecordWorker
include Sidekiq::Worker
def perform(path)
# each time this is run, it is no I/O, just expensive math calculations that take minutes
collection = ExpensiveOperation.new(path).run
if collection && collection.any?
save_records(collection)
else
[]
end
end
end
因为 sidekiq 作业会在后台 运行,我如何通过确认页面通知用户作业已完成?我们不知道作业何时完成,因此 Rails 请求和响应周期在加载确认页面时无法确定任何内容。确认页面是否应该只说 "Processing..." 然后让 Faye 在作业完成后更新页面?
在您的应用程序中添加一个 RecordJobs
模型,用于存储谁上传了记录、记录数、上传时间等。
每次有人上传新记录时创建一个新的 record_job
并将其 id
传递给工作人员。工作人员可以更新该实例以指示其进度。
同时,应用程序可以查询现有的 record_job
并显示其进度。这可以在用户重新加载页面时通过主动轮询或网络套接字(取决于您的需要)来完成。
使用 ActionCable,这里是带有 Report 通道的示例
在routes.rb中添加以下行
mount ActionCable.server => '/cable'
使用以下代码在 app/channels 中创建一个 ReportChannel.rb
class ReportChannel < ApplicationCable::Channel
def subscribed
stream_from "report_#{current_user.id}"
end
end
使用以下代码在 app/assets/javascripts/channels 中创建 reports.coffee
window.App.Channels ||= {}
window.App.Channels.Report ||= {}
window.App.Channels.Report.subscribe = ->
App.report = App.cable.subscriptions.create "ReportChannel",
connected: ->
console.log('connected ')
disconnected: ->
console.log('diconnected ')
received: (data) ->
console.log('returned ')
data = $.parseJSON(data)
#write your code here to update or notify user#
并在作业末尾添加以下行
ActionCable.server.broadcast("*report_*#{current_user_id}", data_in_json_format)
用您的特定型号替换报告
看起来很简单吧:)