Active Job adapter interface
I've created an Active Job adapter to run my background jobs on Google Cloud Run via Google Cloud Tasks. Although it is the first time for me to create an adapter for Active Job, this is working very well so far.
Creating an Active Job adapter itself is not so hard. You can see that by exploring the repository above. In fact, Active Job adapters are required to implement only two methods:
enqueue_at. For example, let's take a look at the implementation of Active Job Inline, which is one of the built-in implementations of Active Job.
module ActiveJob module QueueAdapters # == Active Job Inline adapter # # When enqueuing jobs with the Inline adapter the job will be executed # immediately. # # To use the Inline set the queue_adapter config to +:inline+. # # Rails.application.config.active_job.queue_adapter = :inline class InlineAdapter def enqueue(job) #:nodoc: Base.execute(job.serialize) end def enqueue_at(*) #:nodoc: raise NotImplementedError, "Use a queueing backend to enqueue jobs in the future. Read more at https://guides.rubyonrails.org/active_job_basics.html" end end end end
This adapter is, as its name suggests, supposed to run the job immediately. The method
enqueue executes a job which it received synchronously by
ActiveJob::Base.execute. Because of the nature of the adapter, it does not support scheduling time when the job should be executed. So
enqueue_at just raises
As you can see, the adapter interface is quite simple. Once you glue your back-end mechanism onto Active Job by implementing an adapter, it can be used via Active Job’s interface.
Adapter lookup mechanism
To use an adapter, you have to tell Active Job which adapter you use like below:
Rails.application.config.active_job.queue_adapter = CloudCuckooLandAdapter.new
Conforming the naming convention of Active Job makes it a little convenience. If
CloudCuckooLandAdapters placed at
ActiveJob::QueueAdapters::CloudCuckooLandAdapter, you can simply pass the symbol of the underscore-ized name without the
Rails.application.config.active_job.queue_adapter = :cloud_cuckoo_land
When passing the adapter name by symbol or string, Active Job expects the adapter class is placed under
Sometimes, asynchronous processing make debugging and testing unnecessarily difficult. Thus, an easy way to disable async processing will be needed. For example, it can be done switching between async and sync by a flag, or overriding methods on test/development environment like below:
module Inlining def enqueue(job, *) Base.execute(job.serialize) end alias enqueue_at enqueue end CloudCuckooLandAdapter.prepend Inlining
activejob and active_job
When I created a rubygem to publish an Active Job adapter, I was a little confused. In spite of the module of Active Job is named
ActiveJob, the gem name is
active_job). It causes a weird results when creating a gem which name is prefixed by
$ bundle gem --coc --mit -t rspec activejob-cloud_cuckoo_land_adapter Creating gem 'activejob-cloud_cuckoo_land_adapter'... MIT License enabled in config Code of conduct enabled in config create activejob-cloud_cuckoo_land_adapter/Gemfile create activejob-cloud_cuckoo_land_adapter/lib/activejob/cloud_cuckoo_land_adapter.rb create activejob-cloud_cuckoo_land_adapter/lib/activejob/cloud_cuckoo_land_adapter/version.rb create activejob-cloud_cuckoo_land_adapter/activejob-cloud_cuckoo_land_adapter.gemspec create activejob-cloud_cuckoo_land_adapter/Rakefile create activejob-cloud_cuckoo_land_adapter/README.md create activejob-cloud_cuckoo_land_adapter/bin/console create activejob-cloud_cuckoo_land_adapter/bin/setup create activejob-cloud_cuckoo_land_adapter/.travis.yml create activejob-cloud_cuckoo_land_adapter/.rspec create activejob-cloud_cuckoo_land_adapter/spec/spec_helper.rb create activejob-cloud_cuckoo_land_adapter/spec/activejob/cloud_cuckoo_land_adapter_spec.rb create activejob-cloud_cuckoo_land_adapter/LICENSE.txt create activejob-cloud_cuckoo_land_adapter/CODE_OF_CONDUCT.md Gem 'activejob-cloud_cuckoo_land_adapter' was successfully created. For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html $ cat activejob-cloud_cuckoo_land_adapter/lib/activejob/cloud_cuckoo_land_adapter/version.rb module Activejob module CloudCuckooLandAdapter VERSION = "0.1.0" end end
The generated module name is
Activejob and its directory name is
activejob. Although the result shouldn’t be a surprise, it is better to rename them to
active_job to avoid users’ confusion.