generated from dxw/rails-template
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This gives us a simple background job which anonymises users who have been deactivated for more than 5 years. We introduce the sidekiq-scheduler gem for the purpose of scheduling jobs in a cron-like manner. An ADR justifies the inclusion of sidekiq-scheduler. (Also worth noting that the sidekiq_scheduler_spec basically just checks for typos in the Sidekiq schedule config, in case we ever need to tweak that again or add additional jobs.)
- Loading branch information
1 parent
171073e
commit 90792e5
Showing
10 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
class AnonymiseDeactivatedUsersJob | ||
include Sidekiq::Job | ||
|
||
def perform | ||
User.deactivated.where("deactivated_at < ?", 5.years.ago).each do |user| | ||
AnonymiseUser.new(user:).call | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
doc/architecture/decisions/0040-use-sidekiq-scheduler-for-scheduled-jobs.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# 40. Use sidekiq-scheduler for scheduled jobs | ||
|
||
Date: 2025-02-03 | ||
|
||
## Status | ||
|
||
Accepted | ||
|
||
## Context | ||
|
||
We needed a mechanism for running scheduled background jobs in order to | ||
anonymise users who have been inactive for more than five years. There is no | ||
mechanism currently in place in RODA to handle scheduled background jobs, but | ||
we do have Sidekiq already available to us for running jobs in the background. | ||
|
||
## Decision | ||
|
||
We have decided to use [sidekiq-scheduler][1] as a lightweight scheduled job | ||
solution. A small amount of research suggested that this gem offered a decent | ||
implementation with a standard and well-understood interface (the time-honoured | ||
cron syntax combined with Sidekiq's jobs (_né_ workers)). We also briefly | ||
explored [sidekiq-cron][2] which does almost exactly the same thing, but had | ||
slightly worse documentation. | ||
|
||
## Consequences | ||
|
||
With the addition of this gem, we have a small amount of configuration overhead | ||
and, of course, one additional dependency. Neither of these is particularly | ||
onerous. We now benefit from having a standardised solution for our current | ||
and future scheduled background job requirements. | ||
|
||
[1]: https://github.com/sidekiq-scheduler/sidekiq-scheduler | ||
[2]: https://github.com/sidekiq-cron/sidekiq-cron |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
require "rails_helper" | ||
require "fugit" | ||
|
||
RSpec.describe "sidekiq-scheduler" do | ||
sidekiq_file = File.join(Rails.root, "config", "sidekiq.yml") | ||
schedule = YAML.load_file(sidekiq_file)[:scheduler][:schedule] | ||
|
||
describe "cron syntax" do | ||
schedule.each do |job_name, values| | ||
cron = values["cron"] | ||
it "#{job_name} has correct cron syntax" do | ||
expect { Fugit.do_parse(cron) }.not_to raise_error | ||
end | ||
end | ||
end | ||
|
||
describe "job classes" do | ||
schedule.each do |job_name, values| | ||
klass = values["class"] | ||
it "#{job_name} has #{klass} class in /jobs" do | ||
expect { klass.constantize }.not_to raise_error | ||
end | ||
end | ||
end | ||
|
||
describe "job names" do | ||
schedule.each do |job_name, values| | ||
klass = values["class"] | ||
it "#{job_name} has correct name" do | ||
expect(klass.underscore).to start_with(job_name) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
require "rails_helper" | ||
|
||
RSpec.describe AnonymiseDeactivatedUsersJob, type: :job do | ||
describe "the job" do | ||
subject(:job) { AnonymiseDeactivatedUsersJob.perform_async } | ||
|
||
it "is enqueued" do | ||
expect { job }.to change(AnonymiseDeactivatedUsersJob.jobs, :size).by(1) | ||
end | ||
|
||
it "is drained" do | ||
job | ||
AnonymiseDeactivatedUsersJob.drain | ||
expect(AnonymiseDeactivatedUsersJob.jobs.size).to eq 0 | ||
end | ||
end | ||
|
||
describe "#perform" do | ||
let(:the_recent_past) { 2.years.ago } | ||
let(:the_distant_past) { 6.years.ago } | ||
|
||
it "anonymises a user who has been inactive for more than 5 years" do | ||
create(:beis_user, deactivated_at: the_distant_past) | ||
|
||
described_class.new.perform | ||
|
||
expect(User.first.anonymised_at).not_to eq nil | ||
end | ||
|
||
it "does not anonymise a user who has been inactive for less than 5 years" do | ||
create(:beis_user, deactivated_at: the_recent_past) | ||
|
||
described_class.new.perform | ||
|
||
expect(User.first.anonymised_at).to eq nil | ||
end | ||
|
||
it "anonymises a set of users who were deactivated in the distant past" do | ||
5.times { create(:beis_user, deactivated_at: the_distant_past) } | ||
|
||
described_class.new.perform | ||
|
||
expect(User.deactivated.count).to eq 0 | ||
expect(User.where.not(anonymised_at: nil).count).to eq 5 | ||
end | ||
|
||
it "does not anonymise a set of users who were deactivated in the recent past" do | ||
5.times { create(:beis_user, deactivated_at: the_recent_past) } | ||
|
||
described_class.new.perform | ||
|
||
expect(User.deactivated.count).to eq 5 | ||
expect(User.where.not(anonymised_at: nil).count).to eq 0 | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
require "sidekiq/testing" | ||
Sidekiq::Testing.fake! # qv. https://github.com/sidekiq/sidekiq/wiki/Testing#testing-worker-queueing-fake |