Skip to content

Commit

Permalink
prevent from running multiple same cron jobs (#846)
Browse files Browse the repository at this point in the history
  • Loading branch information
eitoball authored Dec 6, 2021
1 parent 4907f89 commit 5d921e7
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 12 deletions.
39 changes: 27 additions & 12 deletions app/controllers/crons_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,6 @@ class CronsController < ApplicationController
SCRIPT_PATH = Rails.root.join('cron')
CRON_DEFINITIONS = Rails.root.join('cron.yaml')

def configured_job_names
YAML.load_file(CRON_DEFINITIONS)['cron'].map { |d| d['name'] }
end

def runnable?
request.local? && configured_job_names.include?(taskname)
end

def taskname
request.headers['X-Aws-Sqsd-Taskname']
end

def create
return head(:forbidden) unless runnable?

Expand All @@ -27,4 +15,31 @@ def create
render(plain: "Unable to run #{taskname}", status: 500)
end
end

private

def runnable?
request.local? && configured_job_names.include?(taskname) && !running_same_job?
end

def configured_job_names
YAML.load_file(CRON_DEFINITIONS)['cron'].map { |d| d['name'] }
end

def taskname
@taskname ||= request.headers['X-Aws-Sqsd-Taskname']
end

def running_same_job?
res = false
IO.popen('ps ax') do |io|
io.each_line do |line|
if line.chomp.split.last.end_with?(taskname)
res = true
break
end
end
end
res
end
end
47 changes: 47 additions & 0 deletions spec/controllers/crons_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

# frozen_string_literals: true

require 'spec_helper'

RSpec.describe CronsController, type: :controller do
describe 'GET #create' do
before do
@request.env['REMOTE_ADDR'] = '127.0.0.1'
allow(IO).to receive(:popen)
.with('ps ax')
.and_yield(
StringIO.new(<<~STRING)
PID TTY TIME CMD
1 ? S 0:00 bash ./dump_measurements
STRING
)
allow(controller).to receive(:system) # Not to run cron jobs
allow($?).to receive(:success?).and_return(true) # rubocop:disable Style/SpecialGlobalVars
end

describe 'when task exists' do
before do
allow(controller).to receive(:taskname).and_return('dump_clean')
end

it 'returns HTTP 200 OK' do
get :create

expect(response).to have_http_status(200)
end
end

describe 'when task exists but try to run same job' do
before do
allow(controller).to receive(:taskname).and_return('dump_measurements')
end

it 'returns HTTP 403 Forbidden' do
get :create

expect(response).to have_http_status(403)
end
end
end
end

0 comments on commit 5d921e7

Please sign in to comment.