Implement fork-based daemon for scheduling jobs

Extracted from

https://github.com/discourse/discourse/blob/master/lib/demon/sidekiq.rb
This commit is contained in:
Hakan Ensari 2018-09-30 22:20:56 +01:00
parent 1da5f39405
commit fb44818efb
8 changed files with 87 additions and 26 deletions

View File

@ -21,7 +21,7 @@ GEM
minitest-around (0.4.1) minitest-around (0.4.1)
minitest (~> 5.0) minitest (~> 5.0)
mustermann (1.0.3) mustermann (1.0.3)
oj (3.6.10) oj (3.6.11)
ox (2.10.0) ox (2.10.0)
parallel (1.12.1) parallel (1.12.1)
parser (2.5.1.2) parser (2.5.1.2)
@ -46,7 +46,7 @@ GEM
rb-inotify (0.9.10) rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2) ffi (>= 0.5.0, < 2)
redcarpet (3.4.0) redcarpet (3.4.0)
rubocop (0.59.1) rubocop (0.59.2)
jaro_winkler (~> 1.5.1) jaro_winkler (~> 1.5.1)
parallel (~> 1.10) parallel (~> 1.10)
parser (>= 2.5, != 2.5.1.1) parser (>= 2.5, != 2.5.1.1)

View File

@ -7,10 +7,6 @@ require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new scheduler = Rufus::Scheduler.new
trap 'INT' do
scheduler.shutdown
end
scheduler.cron '*/15 15,16,17 * * 1-5' do scheduler.cron '*/15 15,16,17 * * 1-5' do
`rake rates:current` `rake rates:current`
end end

View File

@ -6,6 +6,12 @@ preload_app true
worker_processes worker_process_count worker_processes worker_process_count
timeout 10 timeout 10
before_fork do |_, _| initialized = false
before_fork do |_server, _worker|
Sequel::DATABASES.each(&:disconnect) Sequel::DATABASES.each(&:disconnect)
unless initialized
require 'scheduler'
Scheduler.start
initialized = true
end
end end

View File

@ -7,7 +7,3 @@ services:
VIRTUAL_HOST: localhost VIRTUAL_HOST: localhost
ports: ports:
- "8080:8080" - "8080:8080"
scheduler:
build: .
environment:
APP_ENV: development

View File

@ -10,14 +10,6 @@ services:
max-size: "50m" max-size: "50m"
max-file: "10" max-file: "10"
restart: unless-stopped restart: unless-stopped
scheduler:
env_file: .env
image: hakanensari/frankfurter
logging:
options:
max-size: "50m"
max-file: "10"
restart: unless-stopped
nginx-proxy: nginx-proxy:
image: jwilder/nginx-proxy image: jwilder/nginx-proxy
labels: labels:

View File

@ -13,12 +13,5 @@ services:
- '8080' - '8080'
links: links:
- db - db
scheduler:
command: bin/schedule
entrypoint: bin/wait-for-it.sh db:5432 -s --
environment:
DATABASE_URL: postgres://postgres@db/postgres
links:
- db
volumes: volumes:
data: data:

59
lib/scheduler.rb Normal file
View File

@ -0,0 +1,59 @@
# frozen_string_literal: true
class Scheduler
attr_reader :pid
def self.start
new.start
end
def initialize
@parent_pid = Process.pid
end
def start
return if pid
@pid = fork do
monitor_parent
run
end
monitor_child
end
private
def run
load 'bin/schedule'
end
def monitor_child
return if @child_monitor
@child_monitor = Thread.new do
loop do
sleep 5
unless alive?(pid)
@pid = nil
start
end
end
end
end
def monitor_parent
Thread.new do
loop do
exit unless alive?(@parent_pid)
sleep 1
end
end
end
def alive?(pid)
Process.getpgid(pid)
true
rescue Errno::ESRCH
false
end
end

19
spec/scheduler_spec.rb Normal file
View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
require_relative 'helper'
require 'scheduler'
describe Scheduler do
let :scheduler do
Scheduler.new
end
after do
Process.kill('TERM', scheduler.pid) if scheduler.pid
end
it 'forks a scheduler' do
scheduler.start
Process.getpgid(scheduler.pid) # won't raise Errno::ESRCH
end
end