This library allows you to invoke ActiveRecord instance methods in the background.
Bg::Asyncable
uses concurrent-ruby to execute methods in a different threadBg::Deferrable
uses ActiveJob to execute methods in a background process
class User < ApplicationRecord
include Bg::Asyncable::Behavior # uses concurrent-ruby
include Bg::Deferrable::Behavior # uses ActiveJob
end
user = User.find(params[:id])
# blocking in-process
user.do_hard_work
# non-blocking in-process separate thread
user.async.do_hard_work
# non-blocking out-of-process background job
user.defer.do_hard_work
user.defer(queue: :low, wait: 5.minutes).do_hard_work
Bg::Deferrable
leverages GlobalID::Identification to marshal ActiveRecord instances across process boundaries.
This means that state is not shared between the main process & the process actually executing the method.
- Do not depend on lexically scoped bindings when invoking methods.
- Do not pass unmarshallable types as arguments.
Bg::Deferrable
will prepare arguments for enqueuing, but best practice is to follow Sidekiq's simple parameters rule.
user = User.find(params[:id])
user.defer.do_hard_work 1, true, "foo"
user = User.find(params[:id])
# in memory changes will not be available in Bg::Deferrable invoked methods
user.name = "new value"
# args may not marshal properly
user.defer.do_hard_work :foo, Time.now, instance_of_complex_type
user.defer.do_hard_work do
# blocks are not supported
end
Bg::Asyncable
disallows invoking methods that take blocks as an argument.
- Important: It's your responsibility to protect shared data between threads
user = User.find(params[:id])
user.name = "new value"
user.async.do_hard_work 1, true, "foo"
user.async.do_hard_work :foo, Time.now, instance_of_complex_type
user = User.find(params[:id])
user.async.do_hard_work do
# blocks are not supported
end