Bg
Non-blocking ActiveRecord method invocation
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
Quickstart
Setup
class User < ApplicationRecord
include Bg::Asyncable # uses concurrent-ruby
include Bg::Deferrable # uses ActiveJob
end
Usage
user = User.find(params[:id])
user.do_hard_work # blocking in-process
user.async.do_hard_work # non-blocking in-process
user.defer.do_hard_work # non-blocking out-of-process background job
user.defer(queue: :low, wait: 5.minutes).do_hard_work
Provisos
Bg leverages GlobalID to marshal ActiveRecord instances across thread & process boundaries. This means that state is not shared between the main process/thread with the process/thread actually executing the method.
- Do not depend on lexically scoped bindings when invoking methods with Bg::Deferrable
- Do not pass unmarshallable types as arguments with Bg::Deferrable. Follow Sidekiq's simple parameters rule
Examples
Good
user = User.find(params[:id])
user.update(name: "new value") # persisted changes will be available in Bg invoked methods
user.async.do_hard_work 1, true, "foo", :bar, Time.now
user.defer.do_hard_work 1, true, "foo"
Bad
user = User.find(params[:id])
user.name = "new value" # in memory changes will not be available in Bg invoked methods
user.async.do_hard_work do
# this is dangerous... you better know what you're doing
# best to avoid
end
user.defer.do_hard_work :foo, Time.now # args won't marshal properly
user.defer.do_hard_work do
# blocks are not supported
end