RecurringActiveJob
Adapter agnostic ActiveJob scheduler based on time spent between executions.
You are viewing the README of version [v0.4.00m. You can find other releases here.
Branch | Status |
---|---|
Release | |
Development |
Regular scheduler 10 minute setting:
- Runs every 10 minutes
- Run#1 00:10-00:11
- Run#2 00:20-00:21
- etc
RecurringActiveJob
10 minute setting:
- Runs 10 minutes after the previous run finished
- Run#1 00:10-00:11
- Run#2 00:21-00:22
- etc
Use cases:
- Running jobs constantly without any delay in between
- Running jobs again some time after their execution
- Jobs where the execution time might be longer than the recurring timeframe
Installation
Add this line to your application's Gemfile:
gem 'recurring_active_job'
And then execute:
$ bundle
Or install it yourself as:
$ gem install recurring_active_job
Usage
Recurring jobs are stored in the DB therefore we need the following migration:
bin/rails generate migration CreateRecurringActiveJob
*_create_recurring_active_job.rb
def change
create_table :recurring_active_jobs do |t|
t.string :job_id
t.string :provider_job_id
t.boolean :active, default: true, null: false
t.integer :frequency_seconds, default: 600, null: false
t.boolean :auto_delete, default: true, null: false
t.string :last_error
t.text :last_error_details
t.
end
add_index :recurring_active_jobs, :job_id, unique: true
add_index :recurring_active_jobs, :provider_job_id, unique: true
end
Jobs need to subclass RecurringActiveJob::Base
instead of ActiveJob::Base
:
class MyJob < RecurringActiveJob::Base
def perform(*args)
puts "hi"
end
end
Create a RecurringActiveJob::Model
record and pass its ID when performing the job:
recurring_active_job = RecurringActiveJob::Model.create!(frequency_seconds: 10)
MyJob.perform_later(recurring_active_job_id: recurring_active_job.id)
Testing
Make sure that the class properly inherits:
describe MyJob
it "is a RecurringActiveJob" do
expect(described_class).to be < RecurringActiveJob::Base
end
end
Add a shared context to be included when testing Recurring jobs:
spec/support/shared_context_for_recurring_active_job.rb
RSpec.shared_context "recurring active job" do
let(:recurring_active_job) { create(:recurring_active_job) }
let(:recurring_active_job_params) { { recurring_active_job_id: recurring_active_job.id } }
before do
allow(RecurringActiveJob::Model).to receive(:find).and_return(recurring_active_job)
end
end
RSpec.describe MyJob do
describe "#perform" do
include_context "recurring active job"
# ...
end
end
Custom error handling
RecurringActiveJob
defines the following generic error handling which is required for some features (but raises the original error at the end):
rescue_from(StandardError) do |e|
handle_exception(e)
end
To define your own error handling but keep those features working you can redefine handle_exception
like this:
rescue_from(StandardError) do |e|
handle_exception(e)
end
# ...
def handle_exception(e)
super rescue StandardError
# ...
end
Feedback
Feedback is appreciated.
I can only tailor this project to fit use-cases I know about - which are usually my own ones. If you find that this might be the right direction to solve your problem too but you find that it's suboptimal or lacks features don't hesitate to contact me.
Conventions
This gem is developed using the following conventions:
- Bundler's guide for developing a gem
- Better Specs
- Semantic versioning
- RubyGems' guide on gem naming
- RFC memo about key words used to Indicate Requirement Levels
- Bundler improvements
- Minimal dependencies
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/thisismydesign/recurring_active_job.
License
The gem is available as open source under the terms of the MIT License.