Resque for Cucumber

  • Download Gist
cucumber_external_resque_worker.rb
Ruby
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
class CucumberExternalResqueWorker
DEFAULT_STARTUP_TIMEOUT = 1.minute
COUNTER_KEY = "cucumber:counter"
 
class << self
attr_accessor :pid, :startup_timeout
 
def start
# Call from a Cucumber support file so it is run on startup
return unless Rails.env.cucumber?
if self.pid = fork
start_parent
wait_for_worker_to_start
else
start_child
end
end
 
def install_hooks_on_startup
# Call from a Rails initializer
return unless Rails.env.cucumber?
install_pause_on_start_hook
install_worker_base_counter_patch
end
 
def process_all
# Call from a Cucumber step
unpause
sleep 1 until done?
pause
end
 
def incr
Resque.redis.incr(COUNTER_KEY)
end
 
def decr
Resque.redis.decr(COUNTER_KEY)
end
 
def reset_counter
Resque.redis.set(COUNTER_KEY, 0)
end
 
private
 
def done?
Resque.redis.get(CucumberExternalResqueWorker::COUNTER_KEY).to_i.zero?
end
 
def pause(pid = self.pid)
return unless Rails.env.cucumber?
Process.kill("USR2", pid)
end
 
def unpause
return unless Rails.env.cucumber?
Process.kill("CONT", pid)
end
 
def start_parent
at_exit do
reset_counter
Process.kill("KILL", pid) if pid
end
end
 
def start_child
# Array form of exec() is required here, otherwise the worker is not a direct child process of cucumber.
# If it's not the direct child process then the PID returned from fork() is wrong, which means we can't
# communicate with the worker.
exec('rake', 'resque:work', "QUEUE=*", "RAILS_ENV=cucumber")
end
 
def wait_for_worker_to_start
self.startup_timeout ||= DEFAULT_STARTUP_TIMEOUT
start = Time.now.to_i
while (Time.now.to_i - start) < startup_timeout
return if worker_started?
sleep 1
end
 
raise "Timeout while waiting for the worker to start. Waited #{startup_timeout} seconds."
end
 
def worker_started?
Resque.info[:workers].to_i > 0
end
 
def install_pause_on_start_hook
Resque.before_first_fork do
reset_counter
pause(Process.pid)
end
end
 
def install_worker_base_counter_patch
WorkerBase.class_eval do
class << self
def enqueue_with_counters(*args, &block)
CucumberExternalResqueWorker.incr
enqueue_without_counters(*args, &block)
end
alias_method_chain :enqueue, :counters
 
def perform_with_counters(*args, &block)
perform_without_counters(*args, &block)
ensure
CucumberExternalResqueWorker.decr
end
alias_method_chain :perform, :counters
end
end
end
end
end

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.