Merge pull request #14119 from mkllnk/replace-whenever

Replace whenever with sidekiq scheduler
This commit is contained in:
Maikel
2026-04-01 15:37:33 +11:00
committed by GitHub
9 changed files with 83 additions and 48 deletions

6
.env
View File

@@ -21,12 +21,6 @@ CHECKOUT_ZONE="Australia"
# Find currency codes at http://en.wikipedia.org/wiki/ISO_4217.
CURRENCY="AUD"
# The whenever gem can set the `MAILTO` variable for our cron jobs.
# You can define an email address to notify if any job outputs something.
# But you need a working mail server setup so that the message is delivered.
# See: config/schedule.rb
# SCHEDULE_NOTIFICATIONS="admin@example.com"
# Mail settings
MAIL_HOST="example.com"
MAIL_DOMAIN="example.com"

View File

@@ -118,8 +118,6 @@ gem 'immigrant'
gem 'roo' # read spreadsheets
gem 'spreadsheet_architect' # write spreadsheets
gem 'whenever', require: false
gem 'coffee-rails', '~> 5.0.0'
gem 'angular_rails_csrf'

View File

@@ -245,7 +245,6 @@ GEM
cgi (0.5.1)
childprocess (5.0.0)
choice (0.2.0)
chronic (0.10.2)
coderay (1.1.3)
coffee-rails (5.0.0)
coffee-script (>= 2.2.0)
@@ -968,8 +967,6 @@ GEM
base64
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
whenever (1.1.2)
chronic (>= 0.6.3)
xml-simple (1.1.8)
xpath (3.2.0)
nokogiri (~> 1.8)
@@ -1127,7 +1124,6 @@ DEPENDENCIES
web!
web-console
webmock
whenever
wicked_pdf!
wkhtmltopdf-binary!

15
app/jobs/rake_job.rb Normal file
View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
require "rake"
# Executes a rake task
class RakeJob < ApplicationJob
def perform(task_string)
Rails.application.load_tasks if Rake::Task.tasks.empty?
Rake.application.invoke_task(task_string)
ensure
name, _args = Rake.application.parse_task_string(task_string)
Rake::Task[name].reenable
end
end

View File

@@ -7,6 +7,15 @@ redis_connection_settings = {
Sidekiq.configure_server do |config|
config.redis = redis_connection_settings
config.on(:startup) do
# Load schedule file similar to sidekiq/cli.rb loading the main config.
path = File.expand_path("../sidekiq_scheduler.yml", __dir__)
erb = ERB.new(File.read(path), trim_mode: "-")
Sidekiq.schedule =
YAML.safe_load(erb.result, permitted_classes: [Symbol], aliases: true)
SidekiqScheduler::Scheduler.instance.reload_schedule!
end
end
Sidekiq.configure_client do |config|

View File

@@ -1,24 +0,0 @@
# Force manual loading of rails application to get all env variables from dotenv-rails when running whenever cmd
require File.expand_path('../environment', __FILE__)
require 'whenever'
require 'yaml'
# Learn more: http://github.com/javan/whenever
env "MAILTO", ENV["SCHEDULE_NOTIFICATIONS"] if ENV["SCHEDULE_NOTIFICATIONS"]
# If we use -e with a file containing specs, rspec interprets it and filters out our examples
job_type :run_file, "cd :path; :environment_variable=:environment bundle exec script/rails runner :task :output"
every 1.month, at: '4:30am' do
rake 'ofn:data:remove_transient_data'
end
every 1.day, at: '2:45am' do
rake 'db2fog:clean' if ENV['S3_BACKUPS_BUCKET']
end
every 4.hours do
rake 'db2fog:backup' if ENV['S3_BACKUPS_BUCKET']
end

View File

@@ -7,15 +7,8 @@
- default
- mailers
:scheduler:
:schedule:
HeartbeatJob:
every: ["5m", first_in: "0s"]
SubscriptionPlacementJob:
every: "5m"
SubscriptionConfirmJob:
every: "5m"
TriggerOrderCyclesToOpenJob:
every: "5m"
OrderCycleClosingJob:
every: "5m"
# This config is loaded by sidekiq before dotenv is loading our server config.
# Therefore we load the schedule later. See:
#
# - config/initializers/sidekiq.rb
# - config/sidekiq_scheduler.yml

View File

@@ -0,0 +1,36 @@
# Configure sidekiq-scheduler to run jobs.
#
# - https://github.com/sidekiq-scheduler/sidekiq-scheduler
#
# > Note that every and interval count from when the Sidekiq process (re)starts.
# > So every: '48h' will never run if the Sidekiq process is restarted daily,
# > for example. You can do every: ['48h', first_in: '0s'] to make the job run
# > immediately after a restart, and then have the worker check when it was
# > last run.
#
# Therefore, we use `cron` for jobs that should run at certain times like backups.
HeartbeatJob:
every: ["5m", first_in: "0s"]
SubscriptionPlacementJob:
every: "5m"
SubscriptionConfirmJob:
every: "5m"
TriggerOrderCyclesToOpenJob:
every: "5m"
OrderCycleClosingJob:
every: "5m"
backup:
class: "RakeJob"
args: ["db2fog:backup"]
cron: "0 */4 * * *" # every 4 hours
enabled: <%= ENV.fetch("S3_BACKUPS_BUCKET", false) && true %>
backup_clean:
class: "RakeJob"
args: ["db2fog:clean"]
cron: "45 2 * * *" # every day at 2:45am
enabled: <%= ENV.fetch("S3_BACKUPS_BUCKET", false) && true %>
ofn_clean:
class: "RakeJob"
args: ["ofn:data:remove_transient_data"]
cron: "30 4 1 * *" # every month on the first at 4:30am

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
require "tasks/data/remove_transient_data"
RSpec.describe RakeJob do
let(:task_string) { "ofn:data:remove_transient_data" }
it "calls the removal service" do
expect(RemoveTransientData).to receive(:new).and_call_original
RakeJob.perform_now(task_string)
end
it "can be called several times" do
expect(RemoveTransientData).to receive(:new).twice.and_call_original
RakeJob.perform_now(task_string)
RakeJob.perform_now(task_string)
end
end