From 1a5212b9032816493b2b9b6dc953a7b1cc8e879f Mon Sep 17 00:00:00 2001 From: Dan Buch Date: Tue, 18 Feb 2014 00:58:19 -0500 Subject: [PATCH] Extracting runtime env bits into separate class --- lib/resque/scheduler/cli.rb | 79 ++++++++++--------------------------- lib/resque/scheduler/env.rb | 61 ++++++++++++++++++++++++++++ test/cli_test.rb | 41 ++++--------------- test/env_test.rb | 41 +++++++++++++++++++ 4 files changed, 130 insertions(+), 92 deletions(-) create mode 100644 lib/resque/scheduler/env.rb create mode 100644 test/env_test.rb diff --git a/lib/resque/scheduler/cli.rb b/lib/resque/scheduler/cli.rb index 3ad4bcef..6d37ab19 100644 --- a/lib/resque/scheduler/cli.rb +++ b/lib/resque/scheduler/cli.rb @@ -4,6 +4,20 @@ module Resque module Scheduler + CLI_OPTIONS_ENV_MAPPING = { + app_name: 'APP_NAME', + background: 'BACKGROUND', + dynamic: 'DYNAMIC_SCHEDULE', + env: 'RAILS_ENV', + initializer_path: 'INITIALIZER_PATH', + logfile: 'LOGFILE', + logformat: 'LOGFORMAT', + quiet: 'QUIET', + pidfile: 'PIDFILE', + poll_sleep_amount: 'RESQUE_SCHEDULER_INTERVAL', + verbose: 'VERBOSE' + } + class Cli BANNER = <<-EOF.gsub(/ {6}/, '') Usage: resque-scheduler [options] @@ -95,12 +109,8 @@ def pre_setup end def setup_env - require 'resque' - require 'resque/scheduler' - - setup_backgrounding - setup_pid_file - setup_scheduler_configuration + require_relative 'env' + runtime_env.setup end def run_forever @@ -111,6 +121,10 @@ def run_forever attr_reader :argv, :env + def runtime_env + Resque::Scheduler::Env.new(options) + end + def option_parser OptionParser.new do |opts| opts.banner = BANNER @@ -120,60 +134,9 @@ def option_parser end end - OPTIONS_ENV_MAPPING = { - app_name: 'APP_NAME', - background: 'BACKGROUND', - dynamic: 'DYNAMIC_SCHEDULE', - env: 'RAILS_ENV', - initializer_path: 'INITIALIZER_PATH', - logfile: 'LOGFILE', - logformat: 'LOGFORMAT', - quiet: 'QUIET', - pidfile: 'PIDFILE', - poll_sleep_amount: 'RESQUE_SCHEDULER_INTERVAL', - verbose: 'VERBOSE' - } - def options @options ||= {}.tap do |o| - OPTIONS_ENV_MAPPING.map { |key, envvar| o[key] = env[envvar] } - end - end - - def setup_backgrounding - # Need to set this here for conditional Process.daemon redirect of - # stderr/stdout to /dev/null - Resque::Scheduler.quiet = !!options[:quiet] - - if options[:background] - unless Process.respond_to?('daemon') - abort 'background option is set, which requires ruby >= 1.9' - end - - Process.daemon(true, !Resque::Scheduler.quiet) - Resque.redis.client.reconnect - end - end - - def setup_pid_file - File.open(options[:pidfile], 'w') do |f| - f.puts $PROCESS_ID - end if options[:pidfile] - end - - def setup_scheduler_configuration - Resque::Scheduler.configure do |c| - # These settings are somewhat redundant given the defaults present - # in the attr reader methods. They are left here for clarity and - # to serve as an example of how to use `.configure`. - - c.app_name = options[:app_name] - c.dynamic = !!options[:dynamic] - c.env = options[:env] - c.logfile = options[:logfile] - c.logformat = options[:logformat] - c.poll_sleep_amount = Float(options[:poll_sleep_amount] || '5') - c.verbose = !!options[:verbose] + CLI_OPTIONS_ENV_MAPPING.map { |key, envvar| o[key] = env[envvar] } end end end diff --git a/lib/resque/scheduler/env.rb b/lib/resque/scheduler/env.rb new file mode 100644 index 00000000..61945bcc --- /dev/null +++ b/lib/resque/scheduler/env.rb @@ -0,0 +1,61 @@ +# vim:fileencoding=utf-8 + +module Resque + module Scheduler + class Env + def initialize(options) + @options = options + end + + def setup + require 'resque' + require 'resque/scheduler' + + setup_backgrounding + setup_pid_file + setup_scheduler_configuration + end + + private + + attr_reader :options + + def setup_backgrounding + # Need to set this here for conditional Process.daemon redirect of + # stderr/stdout to /dev/null + Resque::Scheduler.quiet = !!options[:quiet] + + if options[:background] + unless Process.respond_to?('daemon') + abort 'background option is set, which requires ruby >= 1.9' + end + + Process.daemon(true, !Resque::Scheduler.quiet) + Resque.redis.client.reconnect + end + end + + def setup_pid_file + File.open(options[:pidfile], 'w') do |f| + f.puts $PROCESS_ID + end if options[:pidfile] + end + + def setup_scheduler_configuration + Resque::Scheduler.configure do |c| + # These settings are somewhat redundant given the defaults present + # in the attr reader methods. They are left here for clarity and + # to serve as an example of how to use `.configure`. + + c.app_name = options[:app_name] + c.dynamic = !!options[:dynamic] + c.env = options[:env] + c.logfile = options[:logfile] + c.logformat = options[:logformat] + c.poll_sleep_amount = Float(options[:poll_sleep_amount] || '5') + c.verbose = !!options[:verbose] + end + end + end + end +end diff --git a/test/cli_test.rb b/test/cli_test.rb index 010c4cfb..418d9a53 100644 --- a/test/cli_test.rb +++ b/test/cli_test.rb @@ -2,8 +2,14 @@ require_relative 'test_helper' context 'Cli' do + def mock_runtime_env + mock.tap { |m| m.stubs(:setup) } + end + def new_cli(argv = [], env = {}) - Resque::Scheduler::Cli.new(argv, env) + Resque::Scheduler::Cli.new(argv, env).tap do |cli| + cli.stubs(:runtime_env).returns(mock_runtime_env) + end end test 'does not require any positional arguments' do @@ -52,31 +58,6 @@ def new_cli(argv = [], env = {}) assert_equal(true, cli.send(:options)[:background]) end - test 'daemonizes when background is true' do - Process.expects(:daemon) - cli = new_cli(%w(--background)) - cli.pre_run - end - - test 'reconnects redis when background is true' do - Process.stubs(:daemon) - mock_redis_client = mock('redis_client') - mock_redis = mock('redis') - mock_redis.expects(:client).returns(mock_redis_client) - mock_redis_client.expects(:reconnect) - Resque.expects(:redis).returns(mock_redis) - cli = new_cli(%w(--background)) - cli.pre_run - end - - test 'aborts when background is given and Process does not support daemon' do - Process.stubs(:daemon) - Process.expects(:respond_to?).with('daemon').returns(false) - cli = new_cli(%w(--background)) - cli.expects(:abort) - cli.pre_run - end - test 'initializes pidfile from the env' do cli = new_cli([], 'PIDFILE' => 'bar') assert_equal('bar', cli.send(:options)[:pidfile]) @@ -98,14 +79,6 @@ def new_cli(argv = [], env = {}) assert_equal('foo', cli.send(:options)[:pidfile]) end - test 'writes pid to pidfile when given' do - mock_pidfile = mock('pidfile') - mock_pidfile.expects(:puts) - File.expects(:open).with('derp.pid', 'w').yields(mock_pidfile) - cli = new_cli(%w(--pidfile derp.pid)) - cli.pre_run - end - test 'defaults to nil dynamic' do assert_equal(nil, new_cli.send(:options)[:dynamic]) end diff --git a/test/env_test.rb b/test/env_test.rb new file mode 100644 index 00000000..01b543b9 --- /dev/null +++ b/test/env_test.rb @@ -0,0 +1,41 @@ +# vim:fileencoding=utf-8 +require_relative 'test_helper' + +context 'Env' do + def new_env(options = {}) + Resque::Scheduler::Env.new(options) + end + + test 'daemonizes when background is true' do + Process.expects(:daemon) + env = new_env(background: true) + env.setup + end + + test 'reconnects redis when background is true' do + Process.stubs(:daemon) + mock_redis_client = mock('redis_client') + mock_redis = mock('redis') + mock_redis.expects(:client).returns(mock_redis_client) + mock_redis_client.expects(:reconnect) + Resque.expects(:redis).returns(mock_redis) + env = new_env(background: true) + env.setup + end + + test 'aborts when background is given and Process does not support daemon' do + Process.stubs(:daemon) + Process.expects(:respond_to?).with('daemon').returns(false) + env = new_env(background: true) + env.expects(:abort) + env.setup + end + + test 'writes pid to pidfile when given' do + mock_pidfile = mock('pidfile') + mock_pidfile.expects(:puts) + File.expects(:open).with('derp.pid', 'w').yields(mock_pidfile) + env = new_env(pidfile: 'derp.pid') + env.setup + end +end