Rails - 将对象作为参数传递而不进行序列化
Rails - Pass object as argument without serializing
我有一个控制器,我必须从中将对象实例作为参数传递给 Sidekiq 的 Worker class。
我的控制器随叫随到WegWorker.synchronize(@service)
class Api::V2::Events::WegSessionsController < Api::V2::Events::ApplicationController
before_action :load_service
def synchronize
@service.keep_cancelled = params[:keep_cancelled].to_b
if @service.valid_connection?
WegWorker.perform_async(@service)
render json: {
status: :ok,
message: @service.message
}, status: :ok
else
render json: {
status: :unprocessable_entity,
errors: @event.errors.full_messages
}, status: :ok
end
end
.. some code with service object instantiation
end
我的工人class
class WegWorker < ::CarrierWave::Workers::ProcessAsset
include Sidekiq::Worker
sidekiq_options retry: false
def perform(service)
service.synchronize
end
end
但我目前收到的错误是
WARN: NoMethodError: undefined method `synchronize' for "#<WegService:0x0000000013f9abb0>":String
如何在不序列化对象的情况下将对象传递给工作人员?
您正在用这个 WegWorker.perform_async(@service)
排队一个复杂的 Ruby 对象。这不会被正确序列化,您最终会得到一个类似于 "#<WegService:0x0000000013f9abb0>"
的字符串。虽然反序列化 Sidekiq 不会像您期望的那样将其转换为原始 class。
您应该只对简单对象进行排队。因此,您可以将标识符推送到异步作业并在 perform 方法中自己重新实例化服务。
此外,我的建议是阅读 Sidekiq 文档。它们非常小,您可以避免此类错误。 Relevant link 本节。
Sidekiq 作业只能使用 simple parameters,如字符串、数字等。要解决此问题,推荐的方法是在 WegService
上定义以下方法:
class WegService
def self.from_params(params)
new(...) #rehydrate your service using params
end
def to_params
[43, 'foo', 'bar'] # pickle your service
end
# ...
end
然后,你会像这样排队:
WegWorker.perform_async(@service.to_params)
而工人将有:
def perform(params)
WebService.from_params(params).synchronize
end
我有一个控制器,我必须从中将对象实例作为参数传递给 Sidekiq 的 Worker class。
我的控制器随叫随到WegWorker.synchronize(@service)
class Api::V2::Events::WegSessionsController < Api::V2::Events::ApplicationController
before_action :load_service
def synchronize
@service.keep_cancelled = params[:keep_cancelled].to_b
if @service.valid_connection?
WegWorker.perform_async(@service)
render json: {
status: :ok,
message: @service.message
}, status: :ok
else
render json: {
status: :unprocessable_entity,
errors: @event.errors.full_messages
}, status: :ok
end
end
.. some code with service object instantiation
end
我的工人class
class WegWorker < ::CarrierWave::Workers::ProcessAsset
include Sidekiq::Worker
sidekiq_options retry: false
def perform(service)
service.synchronize
end
end
但我目前收到的错误是
WARN: NoMethodError: undefined method `synchronize' for "#<WegService:0x0000000013f9abb0>":String
如何在不序列化对象的情况下将对象传递给工作人员?
您正在用这个 WegWorker.perform_async(@service)
排队一个复杂的 Ruby 对象。这不会被正确序列化,您最终会得到一个类似于 "#<WegService:0x0000000013f9abb0>"
的字符串。虽然反序列化 Sidekiq 不会像您期望的那样将其转换为原始 class。
您应该只对简单对象进行排队。因此,您可以将标识符推送到异步作业并在 perform 方法中自己重新实例化服务。
此外,我的建议是阅读 Sidekiq 文档。它们非常小,您可以避免此类错误。 Relevant link 本节。
Sidekiq 作业只能使用 simple parameters,如字符串、数字等。要解决此问题,推荐的方法是在 WegService
上定义以下方法:
class WegService
def self.from_params(params)
new(...) #rehydrate your service using params
end
def to_params
[43, 'foo', 'bar'] # pickle your service
end
# ...
end
然后,你会像这样排队:
WegWorker.perform_async(@service.to_params)
而工人将有:
def perform(params)
WebService.from_params(params).synchronize
end