resque-admin-scheduler 1.0.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/bin/migrate_to_timestamps_set.rb +16 -0
  3. data/exe/resque-scheduler +2 -2
  4. data/lib/resque/scheduler/cli.rb +6 -6
  5. data/lib/resque/scheduler/delaying_extensions.rb +14 -14
  6. data/lib/resque/scheduler/env.rb +7 -7
  7. data/lib/resque/scheduler/lock.rb +1 -1
  8. data/lib/resque/scheduler/locking.rb +7 -7
  9. data/lib/resque/scheduler/logger_builder.rb +4 -4
  10. data/lib/resque/scheduler/scheduling_extensions.rb +4 -4
  11. data/lib/resque/scheduler/server/views/delayed.erb +4 -4
  12. data/lib/resque/scheduler/server/views/search.erb +1 -1
  13. data/lib/resque/scheduler/server.rb +37 -37
  14. data/lib/resque/scheduler/signal_handling.rb +1 -1
  15. data/lib/resque/scheduler/tasks.rb +6 -6
  16. data/lib/resque/scheduler/util.rb +4 -4
  17. data/lib/resque/scheduler_admin/cli.rb +147 -0
  18. data/lib/resque/scheduler_admin/delaying_extensions.rb +324 -0
  19. data/lib/resque/scheduler_admin/env.rb +89 -0
  20. data/lib/resque/scheduler_admin/lock.rb +4 -0
  21. data/lib/resque/scheduler_admin/locking.rb +104 -0
  22. data/lib/resque/scheduler_admin/logger_builder.rb +72 -0
  23. data/lib/resque/scheduler_admin/scheduling_extensions.rb +141 -0
  24. data/lib/resque/scheduler_admin/server/views/delayed.erb +63 -0
  25. data/lib/resque/scheduler_admin/server/views/search.erb +72 -0
  26. data/lib/resque/scheduler_admin/signal_handling.rb +40 -0
  27. data/lib/resque/scheduler_admin/tasks.rb +25 -0
  28. data/lib/resque/scheduler_admin/util.rb +39 -0
  29. data/lib/resque-admin-scheduler.rb +4 -0
  30. data/lib/resque_admin/scheduler/cli.rb +147 -0
  31. data/lib/{resque → resque_admin}/scheduler/configuration.rb +1 -1
  32. data/lib/resque_admin/scheduler/delaying_extensions.rb +324 -0
  33. data/lib/resque_admin/scheduler/env.rb +89 -0
  34. data/lib/{resque → resque_admin}/scheduler/extension.rb +1 -1
  35. data/lib/{resque → resque_admin}/scheduler/failure_handler.rb +2 -2
  36. data/lib/{resque → resque_admin}/scheduler/lock/base.rb +3 -3
  37. data/lib/{resque → resque_admin}/scheduler/lock/basic.rb +4 -4
  38. data/lib/{resque → resque_admin}/scheduler/lock/resilient.rb +4 -4
  39. data/lib/resque_admin/scheduler/lock.rb +4 -0
  40. data/lib/resque_admin/scheduler/locking.rb +104 -0
  41. data/lib/resque_admin/scheduler/logger_builder.rb +72 -0
  42. data/lib/{resque → resque_admin}/scheduler/plugin.rb +1 -1
  43. data/lib/resque_admin/scheduler/scheduling_extensions.rb +141 -0
  44. data/lib/resque_admin/scheduler/server/views/delayed.erb +63 -0
  45. data/lib/{resque → resque_admin}/scheduler/server/views/delayed_schedules.erb +0 -0
  46. data/lib/{resque → resque_admin}/scheduler/server/views/delayed_timestamp.erb +2 -2
  47. data/lib/{resque → resque_admin}/scheduler/server/views/requeue-params.erb +0 -0
  48. data/lib/{resque → resque_admin}/scheduler/server/views/scheduler.erb +7 -7
  49. data/lib/resque_admin/scheduler/server/views/search.erb +72 -0
  50. data/lib/{resque → resque_admin}/scheduler/server/views/search_form.erb +0 -0
  51. data/lib/resque_admin/scheduler/server.rb +268 -0
  52. data/lib/resque_admin/scheduler/signal_handling.rb +40 -0
  53. data/lib/resque_admin/scheduler/tasks.rb +25 -0
  54. data/lib/resque_admin/scheduler/util.rb +39 -0
  55. data/lib/{resque → resque_admin}/scheduler/version.rb +2 -2
  56. data/lib/{resque → resque_admin}/scheduler.rb +44 -44
  57. data/tasks/resque_admin_scheduler.rake +2 -0
  58. metadata +47 -85
  59. data/AUTHORS.md +0 -81
  60. data/CHANGELOG.md +0 -456
  61. data/CODE_OF_CONDUCT.md +0 -74
  62. data/CONTRIBUTING.md +0 -6
  63. data/Gemfile +0 -4
  64. data/LICENSE +0 -23
  65. data/README.md +0 -691
  66. data/Rakefile +0 -21
  67. data/lib/resque-scheduler.rb +0 -4
  68. data/resque-scheduler.gemspec +0 -60
@@ -0,0 +1,72 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ require 'mono_logger'
4
+
5
+ module ResqueAdmin
6
+ module Scheduler
7
+ # Just builds a logger, with specified verbosity and destination.
8
+ # The simplest example:
9
+ #
10
+ # ResqueAdmin::Scheduler::LoggerBuilder.new.build
11
+ class LoggerBuilder
12
+ # Initializes new instance of the builder
13
+ #
14
+ # Pass :opts Hash with
15
+ # - :quiet if logger needs to be silent for all levels. Default - false
16
+ # - :verbose if there is a need in debug messages. Default - false
17
+ # - :log_dev to output logs into a desired file. Default - STDOUT
18
+ # - :format log format, either 'text' or 'json'. Default - 'text'
19
+ #
20
+ # Example:
21
+ #
22
+ # LoggerBuilder.new(
23
+ # :quiet => false, :verbose => true, :log_dev => 'log/scheduler_admin.log'
24
+ # )
25
+ def initialize(opts = {})
26
+ @quiet = !!opts[:quiet]
27
+ @verbose = !!opts[:verbose]
28
+ @log_dev = opts[:log_dev] || $stdout
29
+ @format = opts[:format] || 'text'
30
+ end
31
+
32
+ # Returns an instance of MonoLogger
33
+ def build
34
+ logger = MonoLogger.new(@log_dev)
35
+ logger.level = level
36
+ logger.formatter = send(:"#{@format}_formatter")
37
+ logger
38
+ end
39
+
40
+ private
41
+
42
+ def level
43
+ if @verbose && !@quiet
44
+ MonoLogger::DEBUG
45
+ elsif !@quiet
46
+ MonoLogger::INFO
47
+ else
48
+ MonoLogger::FATAL
49
+ end
50
+ end
51
+
52
+ def text_formatter
53
+ proc do |severity, datetime, _progname, msg|
54
+ "resque_admin-scheduler_admin: [#{severity}] #{datetime.iso8601}: #{msg}\n"
55
+ end
56
+ end
57
+
58
+ def json_formatter
59
+ proc do |severity, datetime, progname, msg|
60
+ require 'json'
61
+ JSON.dump(
62
+ name: 'resque_admin-scheduler_admin',
63
+ progname: progname,
64
+ level: severity,
65
+ timestamp: datetime.iso8601,
66
+ msg: msg
67
+ ) + "\n"
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,141 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ module ResqueAdmin
4
+ module Scheduler
5
+ module SchedulingExtensions
6
+ # Accepts a new schedule configuration of the form:
7
+ #
8
+ # {
9
+ # "MakeTea" => {
10
+ # "every" => "1m" },
11
+ # "some_name" => {
12
+ # "cron" => "5/* * * *",
13
+ # "class" => "DoSomeWork",
14
+ # "args" => "work on this string",
15
+ # "description" => "this thing works it"s butter off" },
16
+ # ...
17
+ # }
18
+ #
19
+ # Hash keys can be anything and are used to describe and reference
20
+ # the scheduled job. If the "class" argument is missing, the key
21
+ # is used implicitly as "class" argument - in the "MakeTea" example,
22
+ # "MakeTea" is used both as job name and resque_admin worker class.
23
+ #
24
+ # Any jobs that were in the old schedule, but are not
25
+ # present in the new schedule, will be removed.
26
+ #
27
+ # :cron can be any cron scheduling string
28
+ #
29
+ # :every can be used in lieu of :cron. see rufus-scheduler_admin's 'every'
30
+ # usage for valid syntax. If :cron is present it will take precedence
31
+ # over :every.
32
+ #
33
+ # :class must be a resque_admin worker class. If it is missing, the job name
34
+ # (hash key) will be used as :class.
35
+ #
36
+ # :args can be any yaml which will be converted to a ruby literal and
37
+ # passed in a params. (optional)
38
+ #
39
+ # :rails_envs is the list of envs where the job gets loaded. Envs are
40
+ # comma separated (optional)
41
+ #
42
+ # :description is just that, a description of the job (optional). If
43
+ # params is an array, each element in the array is passed as a separate
44
+ # param, otherwise params is passed in as the only parameter to
45
+ # perform.
46
+ def schedule=(schedule_hash)
47
+ @non_persistent_schedules = nil
48
+ prepared_schedules = prepare_schedules(schedule_hash)
49
+
50
+ prepared_schedules.each do |schedule, config|
51
+ set_schedule(schedule, config, false)
52
+ end
53
+
54
+ # ensure only return the successfully saved data!
55
+ reload_schedule!
56
+ end
57
+
58
+ # Returns the schedule hash
59
+ def schedule
60
+ @schedule ||= all_schedules
61
+ @schedule || {}
62
+ end
63
+
64
+ # reloads the schedule from redis and memory
65
+ def reload_schedule!
66
+ @schedule = all_schedules
67
+ end
68
+
69
+ # gets the schedules as it exists in redis
70
+ def all_schedules
71
+ non_persistent_schedules.merge(persistent_schedules)
72
+ end
73
+
74
+ # Create or update a schedule with the provided name and configuration.
75
+ #
76
+ # Note: values for class and custom_job_class need to be strings,
77
+ # not constants.
78
+ #
79
+ # ResqueAdmin.set_schedule('some_job', {:class => 'SomeJob',
80
+ # :every => '15mins',
81
+ # :queue => 'high',
82
+ # :args => '/tmp/poop'})
83
+ #
84
+ # Preventing a reload is optional and available to batch operations
85
+ def set_schedule(name, config, reload = true)
86
+ persist = config.delete(:persist) || config.delete('persist')
87
+
88
+ if persist
89
+ redis.hset(:persistent_schedules, name, encode(config))
90
+ else
91
+ non_persistent_schedules[name] = decode(encode(config))
92
+ end
93
+
94
+ redis.sadd(:schedules_changed, name)
95
+ reload_schedule! if reload
96
+ end
97
+
98
+ # retrive the schedule configuration for the given name
99
+ def fetch_schedule(name)
100
+ schedule[name]
101
+ end
102
+
103
+ # remove a given schedule by name
104
+ def remove_schedule(name)
105
+ non_persistent_schedules.delete(name)
106
+ redis.hdel(:persistent_schedules, name)
107
+ redis.sadd(:schedules_changed, name)
108
+
109
+ reload_schedule!
110
+ end
111
+
112
+ private
113
+
114
+ # we store our non-persistent schedules in this hash
115
+ def non_persistent_schedules
116
+ @non_persistent_schedules ||= {}
117
+ end
118
+
119
+ # reads the persistent schedules from redis
120
+ def persistent_schedules
121
+ redis.hgetall(:persistent_schedules).tap do |h|
122
+ h.each do |name, config|
123
+ h[name] = decode(config)
124
+ end
125
+ end
126
+ end
127
+
128
+ def prepare_schedules(schedule_hash)
129
+ prepared_hash = {}
130
+ schedule_hash.each do |name, job_spec|
131
+ job_spec = job_spec.dup
132
+ unless job_spec.key?('class') || job_spec.key?(:class)
133
+ job_spec['class'] = name
134
+ end
135
+ prepared_hash[name] = job_spec
136
+ end
137
+ prepared_hash
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,63 @@
1
+ <h1>Delayed Jobs</h1>
2
+ <%- size = resque_admin.delayed_queue_schedule_size %>
3
+
4
+ <%= scheduler_admin_view :search_form, layout: false %>
5
+
6
+ <p style="font-color: red; font-weight: bold;">
7
+ <%= @error_message %>
8
+ </p>
9
+
10
+ <p class='intro'>
11
+ This list below contains the timestamps for scheduled delayed jobs.
12
+ Server local time: <%= Time.now %>
13
+ </p>
14
+
15
+ <p class='sub'>
16
+ Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%= size %></b> timestamps
17
+ </p>
18
+
19
+ <table>
20
+ <tr>
21
+ <th></th>
22
+ <th>Timestamp</th>
23
+ <th>Job count</th>
24
+ <th>Class</th>
25
+ <th>Args</th>
26
+ <th>All schedules</th>
27
+ </tr>
28
+ <% resque_admin.delayed_queue_peek(start, 20).each do |timestamp| %>
29
+ <tr>
30
+ <td>
31
+ <form action="<%= u "/delayed/queue_now" %>" method="post">
32
+ <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
33
+ <input type="submit" value="Queue now">
34
+ </form>
35
+ </td>
36
+ <td><a href="<%= u "delayed/#{timestamp}" %>"><%= format_time(Time.at(timestamp)) %></a></td>
37
+ <td><%= delayed_timestamp_size = resque_admin.delayed_timestamp_size(timestamp) %></td>
38
+ <% job = resque_admin.delayed_timestamp_peek(timestamp, 0, 1).first %>
39
+ <td>
40
+ <% if job && delayed_timestamp_size == 1 %>
41
+ <%= h(job['class']) %>
42
+ <% else %>
43
+ <a href="<%= u "delayed/#{timestamp}" %>">see details</a>
44
+ <% end %>
45
+ </td>
46
+ <td><%= h(show_job_arguments(job['args'])) if job && delayed_timestamp_size == 1 %></td>
47
+ <td>
48
+ <% if job %>
49
+ <a href="<%=u URI("/delayed/jobs/#{job['class']}?args=" + URI.encode(job['args'].to_json)) %>">All schedules</a>
50
+ <% end %>
51
+ </td>
52
+ </tr>
53
+ <% end %>
54
+ </table>
55
+
56
+ <% if size > 0 %>
57
+ <br>
58
+ <form method="POST" action="<%=u 'delayed/clear'%>" class='clear-delayed'>
59
+ <input type='submit' name='' value='Clear Delayed Jobs' />
60
+ </form>
61
+ <% end %>
62
+
63
+ <%= partial :next_more, :start => start, :size => size %>
@@ -0,0 +1,72 @@
1
+ <h1>Search Results</h1>
2
+ <%= scheduler_admin_view :search_form, layout: false %>
3
+ <hr>
4
+ <% delayed = @jobs.select { |j| j['where_at'] == 'delayed' } %>
5
+ <h1>Delayed jobs</h1>
6
+ <table class='jobs'>
7
+ <tr>
8
+ <th></th>
9
+ <th></th>
10
+ <th>Timestamp</th>
11
+ <th>Class</th>
12
+ <th>Args</th>
13
+ </tr>
14
+ <% delayed.each do |job| %>
15
+ <tr>
16
+ <td>
17
+ <form action="<%= u "/delayed/queue_now" %>" method="post">
18
+ <input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
19
+ <input type="submit" value="Queue now">
20
+ </form>
21
+ </td>
22
+ <td>
23
+ <form action="<%= u "/delayed/cancel_now" %>" method="post">
24
+ <input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
25
+ <input type="hidden" name="klass" value="<%= job['class'] %>">
26
+ <input type="hidden" name="args" value="<%= h(ResqueAdmin.encode job['args']) %>">
27
+ <input type="submit" value="Cancel Job">
28
+ </form>
29
+ </td>
30
+ <td class='args'><%= format_time(Time.at(job['timestamp'])) %></td>
31
+ <td class='class'><%= job['class'] %></td>
32
+ <td class='args'><%= h job['args'].inspect %></td>
33
+ </tr>
34
+ <% end %>
35
+ </table>
36
+ </h1>
37
+
38
+ <% queued = @jobs.select { |j| j['where_at'] == 'queued' } %>
39
+ <h1>Queued jobs</h1>
40
+ <table class='jobs'>
41
+ <tr>
42
+ <th>Queue</th>
43
+ <th>Class</th>
44
+ <th>Args</th>
45
+ </tr>
46
+ <% queued.each do |job| %>
47
+ <tr>
48
+ <td class='class'><%= job['queue'] %></td>
49
+ <td class='class'><%= job['class'] %></td>
50
+ <td class='args'><%= h job['args'].inspect %></td>
51
+ </tr>
52
+ <% end %>
53
+ </table>
54
+
55
+ <% working = @jobs.select { |j| j['where_at'] == 'working' } %>
56
+ <h1>Working jobs</h1>
57
+ <table class='jobs'>
58
+ <tr>
59
+ <th>Queue</th>
60
+ <th>Class</th>
61
+ <th>Args</th>
62
+ </tr>
63
+ <% working.each do |job| %>
64
+ <tr>
65
+ <td class='class'><%= job['queue'] %></td>
66
+ <td class='class'><%= job['class'] %></td>
67
+ <td class='args'><%= h job['args'].inspect %></td>
68
+ </tr>
69
+ <% end %>
70
+ </table>
71
+
72
+
@@ -0,0 +1,40 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ module ResqueAdmin
4
+ module Scheduler
5
+ module SignalHandling
6
+ attr_writer :signal_queue
7
+
8
+ def signal_queue
9
+ @signal_queue ||= []
10
+ end
11
+
12
+ # For all signals, set the shutdown flag and wait for current
13
+ # poll/enqueing to finish (should be almost instant). In the
14
+ # case of sleeping, exit immediately.
15
+ def register_signal_handlers
16
+ (Signal.list.keys & %w(INT TERM USR1 USR2 QUIT)).each do |sig|
17
+ trap(sig) do
18
+ signal_queue << sig
19
+ # break sleep in the primary scheduler_admin thread, alowing
20
+ # the signal queue to get processed as soon as possible.
21
+ @th.wakeup if @th && @th.alive?
22
+ end
23
+ end
24
+ end
25
+
26
+ def handle_signals
27
+ loop do
28
+ sig = signal_queue.shift
29
+ break unless sig
30
+ log! "Got #{sig} signal"
31
+ case sig
32
+ when 'INT', 'TERM', 'QUIT' then shutdown
33
+ when 'USR1' then print_schedule
34
+ when 'USR2' then reload_schedule!
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ require 'resque_admin/tasks'
4
+ require 'resque_admin-scheduler_admin'
5
+
6
+ namespace :resque_admin do
7
+ task :setup
8
+
9
+ def scheduler_admin_cli
10
+ @scheduler_admin_cli ||= ResqueAdmin::Scheduler::Cli.new(
11
+ %W(#{ENV['RESQUE_SCHEDULER_OPTIONS']})
12
+ )
13
+ end
14
+
15
+ desc 'Start ResqueAdmin Scheduler'
16
+ task scheduler_admin: :scheduler_admin_setup do
17
+ scheduler_admin_cli.setup_env
18
+ scheduler_admin_cli.run_forever
19
+ end
20
+
21
+ task :scheduler_admin_setup do
22
+ scheduler_admin_cli.parse_options
23
+ Rake::Task['resque_admin:setup'].invoke unless scheduler_admin_cli.pre_setup
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ module ResqueAdmin
4
+ module Scheduler
5
+ class Util
6
+ # In order to upgrade to resque_admin(1.25) which has deprecated following
7
+ # methods, we just added these usefull helpers back to use in ResqueAdmin
8
+ # Scheduler. refer to:
9
+ # https://github.com/resque_admin/resque_admin-scheduler_admin/pull/273
10
+
11
+ def self.constantize(camel_cased_word)
12
+ camel_cased_word = camel_cased_word.to_s
13
+
14
+ if camel_cased_word.include?('-')
15
+ camel_cased_word = classify(camel_cased_word)
16
+ end
17
+
18
+ names = camel_cased_word.split('::')
19
+ names.shift if names.empty? || names.first.empty?
20
+
21
+ constant = Object
22
+ names.each do |name|
23
+ args = Module.method(:const_get).arity != 1 ? [false] : []
24
+
25
+ constant = if constant.const_defined?(name, *args)
26
+ constant.const_get(name)
27
+ else
28
+ constant.const_missing(name)
29
+ end
30
+ end
31
+ constant
32
+ end
33
+
34
+ def self.classify(dashed_word)
35
+ dashed_word.split('-').map(&:capitalize).join
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,4 @@
1
+ # vim:fileencoding=utf-8
2
+ require_relative 'resque_admin/scheduler'
3
+
4
+ ResqueAdmin.extend ResqueAdmin::Scheduler::Extension
@@ -0,0 +1,147 @@
1
+ # vim:fileencoding=utf-8
2
+
3
+ require 'optparse'
4
+
5
+ module ResqueAdmin
6
+ module Scheduler
7
+ CLI_OPTIONS_ENV_MAPPING = {
8
+ app_name: 'APP_NAME',
9
+ background: 'BACKGROUND',
10
+ dynamic: 'DYNAMIC_SCHEDULE',
11
+ env: 'RAILS_ENV',
12
+ initializer_path: 'INITIALIZER_PATH',
13
+ logfile: 'LOGFILE',
14
+ logformat: 'LOGFORMAT',
15
+ quiet: 'QUIET',
16
+ pidfile: 'PIDFILE',
17
+ poll_sleep_amount: 'RESQUE_SCHEDULER_INTERVAL',
18
+ verbose: 'VERBOSE'
19
+ }.freeze
20
+
21
+ class Cli
22
+ BANNER = <<-EOF.gsub(/ {6}/, '')
23
+ Usage: resque_admin-scheduler [options]
24
+
25
+ Runs a resque_admin scheduler process directly (rather than via rake).
26
+
27
+ EOF
28
+ OPTIONS = [
29
+ {
30
+ args: ['-n', '--app-name [APP_NAME]',
31
+ 'Application name for procline'],
32
+ callback: ->(options) { ->(n) { options[:app_name] = n } }
33
+ },
34
+ {
35
+ args: ['-B', '--background', 'Run in the background [BACKGROUND]'],
36
+ callback: ->(options) { ->(b) { options[:background] = b } }
37
+ },
38
+ {
39
+ args: ['-D', '--dynamic-schedule',
40
+ 'Enable dynamic scheduling [DYNAMIC_SCHEDULE]'],
41
+ callback: ->(options) { ->(d) { options[:dynamic] = d } }
42
+ },
43
+ {
44
+ args: ['-E', '--environment [RAILS_ENV]', 'Environment name'],
45
+ callback: ->(options) { ->(e) { options[:env] = e } }
46
+ },
47
+ {
48
+ args: ['-I', '--initializer-path [INITIALIZER_PATH]',
49
+ 'Path to optional initializer ruby file'],
50
+ callback: ->(options) { ->(i) { options[:initializer_path] = i } }
51
+ },
52
+ {
53
+ args: ['-i', '--interval [RESQUE_SCHEDULER_INTERVAL]',
54
+ 'Interval for checking if a scheduled job must run'],
55
+ callback: ->(options) { ->(i) { options[:poll_sleep_amount] = i } }
56
+ },
57
+ {
58
+ args: ['-l', '--logfile [LOGFILE]', 'Log file name'],
59
+ callback: ->(options) { ->(l) { options[:logfile] = l } }
60
+ },
61
+ {
62
+ args: ['-F', '--logformat [LOGFORMAT]', 'Log output format'],
63
+ callback: ->(options) { ->(f) { options[:logformat] = f } }
64
+ },
65
+ {
66
+ args: ['-P', '--pidfile [PIDFILE]', 'PID file name'],
67
+ callback: ->(options) { ->(p) { options[:pidfile] = p } }
68
+ },
69
+ {
70
+ args: ['-q', '--quiet', 'Run with minimal output [QUIET]'],
71
+ callback: ->(options) { ->(q) { options[:quiet] = q } }
72
+ },
73
+ {
74
+ args: ['-v', '--verbose', 'Run with verbose output [VERBOSE]'],
75
+ callback: ->(options) { ->(v) { options[:verbose] = v } }
76
+ }
77
+ ].freeze
78
+
79
+ def self.run!(argv = ARGV, env = ENV)
80
+ new(argv, env).run!
81
+ end
82
+
83
+ def initialize(argv = ARGV, env = ENV)
84
+ @argv = argv
85
+ @env = env
86
+ end
87
+
88
+ def run!
89
+ pre_run
90
+ run_forever
91
+ end
92
+
93
+ def pre_run
94
+ parse_options
95
+ pre_setup
96
+ setup_env
97
+ end
98
+
99
+ def parse_options
100
+ option_parser.parse!(argv.dup)
101
+ end
102
+
103
+ def pre_setup
104
+ if options[:initializer_path]
105
+ load options[:initializer_path].to_s.strip
106
+ else
107
+ false
108
+ end
109
+ end
110
+
111
+ def setup_env
112
+ require_relative 'env'
113
+ runtime_env.setup
114
+ end
115
+
116
+ def run_forever
117
+ ResqueAdmin::Scheduler.run
118
+ end
119
+
120
+ private
121
+
122
+ attr_reader :argv, :env
123
+
124
+ def runtime_env
125
+ @runtime_env ||= ResqueAdmin::Scheduler::Env.new(options)
126
+ end
127
+
128
+ def option_parser
129
+ OptionParser.new do |opts|
130
+ opts.banner = BANNER
131
+ opts.version = ResqueAdmin::Scheduler::VERSION
132
+ OPTIONS.each do |opt|
133
+ opts.on(*opt[:args], &opt[:callback].call(options))
134
+ end
135
+ end
136
+ end
137
+
138
+ def options
139
+ @options ||= {}.tap do |o|
140
+ CLI_OPTIONS_ENV_MAPPING.each do |key, envvar|
141
+ o[key] = env[envvar] if env.include?(envvar)
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
@@ -1,6 +1,6 @@
1
1
  # vim:fileencoding=utf-8
2
2
 
3
- module Resque
3
+ module ResqueAdmin
4
4
  module Scheduler
5
5
  module Configuration
6
6
  # Allows for block-style configuration