resque-scheduler 2.5.1 → 4.10.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +12 -0
- data/.github/funding.yml +4 -0
- data/.github/workflows/codeql-analysis.yml +59 -0
- data/.github/workflows/rubocop.yml +27 -0
- data/.github/workflows/ruby.yml +81 -0
- data/AUTHORS.md +25 -0
- data/CHANGELOG.md +539 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +26 -2
- data/README.md +291 -70
- data/Rakefile +8 -19
- data/exe/resque-scheduler +5 -0
- data/lib/resque/scheduler/cli.rb +147 -0
- data/lib/resque/scheduler/configuration.rb +102 -0
- data/lib/resque/scheduler/delaying_extensions.rb +371 -0
- data/lib/resque/scheduler/env.rb +85 -0
- data/lib/resque/scheduler/extension.rb +13 -0
- data/lib/resque/scheduler/failure_handler.rb +11 -0
- data/lib/resque/scheduler/lock/base.rb +13 -4
- data/lib/resque/scheduler/lock/basic.rb +4 -5
- data/lib/resque/scheduler/lock/resilient.rb +52 -43
- data/lib/resque/scheduler/lock.rb +2 -1
- data/lib/resque/scheduler/locking.rb +104 -0
- data/lib/resque/scheduler/logger_builder.rb +83 -0
- data/lib/resque/scheduler/plugin.rb +31 -0
- data/lib/resque/scheduler/scheduling_extensions.rb +142 -0
- data/lib/{resque_scheduler → resque/scheduler}/server/views/delayed.erb +21 -12
- data/lib/{resque_scheduler → resque/scheduler}/server/views/delayed_schedules.erb +1 -1
- data/lib/{resque_scheduler → resque/scheduler}/server/views/delayed_timestamp.erb +1 -1
- data/lib/resque/scheduler/server/views/scheduler.erb +58 -0
- data/lib/{resque_scheduler → resque/scheduler}/server/views/search.erb +4 -7
- data/lib/{resque_scheduler → resque/scheduler}/server/views/search_form.erb +1 -5
- data/lib/resque/scheduler/server.rb +268 -0
- data/lib/resque/scheduler/signal_handling.rb +40 -0
- data/lib/{resque_scheduler → resque/scheduler}/tasks.rb +3 -6
- data/lib/resque/scheduler/util.rb +39 -0
- data/lib/resque/scheduler/version.rb +7 -0
- data/lib/resque/scheduler.rb +271 -199
- data/lib/resque-scheduler.rb +3 -1
- data/resque-scheduler.gemspec +53 -20
- metadata +176 -132
- data/.gitignore +0 -11
- data/.rubocop.yml +0 -129
- data/.simplecov +0 -1
- data/.travis.yml +0 -21
- data/HISTORY.md +0 -226
- data/ROADMAP.md +0 -10
- data/bin/resque-scheduler +0 -5
- data/examples/Rakefile +0 -2
- data/examples/config/initializers/resque-web.rb +0 -37
- data/examples/dynamic-scheduling/README.md +0 -28
- data/examples/dynamic-scheduling/app/jobs/fix_schedules_job.rb +0 -54
- data/examples/dynamic-scheduling/app/jobs/send_email_job.rb +0 -9
- data/examples/dynamic-scheduling/app/models/user.rb +0 -16
- data/examples/dynamic-scheduling/config/resque.yml +0 -4
- data/examples/dynamic-scheduling/config/static_schedule.yml +0 -7
- data/examples/dynamic-scheduling/lib/tasks/resque.rake +0 -48
- data/examples/run-resque-web +0 -3
- data/lib/resque/scheduler_locking.rb +0 -91
- data/lib/resque_scheduler/cli.rb +0 -160
- data/lib/resque_scheduler/logger_builder.rb +0 -70
- data/lib/resque_scheduler/plugin.rb +0 -28
- data/lib/resque_scheduler/server/views/scheduler.erb +0 -36
- data/lib/resque_scheduler/server.rb +0 -182
- data/lib/resque_scheduler/util.rb +0 -34
- data/lib/resque_scheduler/version.rb +0 -5
- data/lib/resque_scheduler.rb +0 -386
- data/script/migrate_to_timestamps_set.rb +0 -14
- data/tasks/resque_scheduler.rake +0 -2
- data/test/cli_test.rb +0 -286
- data/test/delayed_queue_test.rb +0 -449
- data/test/redis-test.conf +0 -108
- data/test/resque-web_test.rb +0 -199
- data/test/scheduler_args_test.rb +0 -190
- data/test/scheduler_hooks_test.rb +0 -23
- data/test/scheduler_locking_test.rb +0 -242
- data/test/scheduler_setup_test.rb +0 -95
- data/test/scheduler_task_test.rb +0 -35
- data/test/scheduler_test.rb +0 -344
- data/test/support/redis_instance.rb +0 -134
- data/test/test_helper.rb +0 -131
- /data/lib/{resque_scheduler → resque/scheduler}/server/views/requeue-params.erb +0 -0
data/lib/resque_scheduler/cli.rb
DELETED
@@ -1,160 +0,0 @@
|
|
1
|
-
# vim:fileencoding=utf-8
|
2
|
-
|
3
|
-
require 'optparse'
|
4
|
-
|
5
|
-
module ResqueScheduler
|
6
|
-
class Cli
|
7
|
-
BANNER = <<-EOF.gsub(/ {6}/, '')
|
8
|
-
Usage: resque-scheduler [options]
|
9
|
-
|
10
|
-
Runs a resque scheduler process directly (rather than via rake).
|
11
|
-
|
12
|
-
EOF
|
13
|
-
OPTIONS = [
|
14
|
-
{
|
15
|
-
args: ['-n', '--app-name [APP_NAME]', 'Application name for procline'],
|
16
|
-
callback: ->(options) { ->(n) { options[:app_name] = n } }
|
17
|
-
},
|
18
|
-
{
|
19
|
-
args: ['-B', '--background', 'Run in the background [BACKGROUND]'],
|
20
|
-
callback: ->(options) { ->(b) { options[:background] = b } }
|
21
|
-
},
|
22
|
-
{
|
23
|
-
args: ['-D', '--dynamic-schedule',
|
24
|
-
'Enable dynamic scheduling [DYNAMIC_SCHEDULE]'],
|
25
|
-
callback: ->(options) { ->(d) { options[:dynamic] = d } }
|
26
|
-
},
|
27
|
-
{
|
28
|
-
args: ['-E', '--environment [RAILS_ENV]', 'Environment name'],
|
29
|
-
callback: ->(options) { ->(e) { options[:env] = e } }
|
30
|
-
},
|
31
|
-
{
|
32
|
-
args: ['-I', '--initializer-path [INITIALIZER_PATH]',
|
33
|
-
'Path to optional initializer ruby file'],
|
34
|
-
callback: ->(options) { ->(i) { options[:initializer_path] = i } }
|
35
|
-
},
|
36
|
-
{
|
37
|
-
args: ['-i', '--interval [RESQUE_SCHEDULER_INTERVAL]',
|
38
|
-
'Interval for checking if a scheduled job must run'],
|
39
|
-
callback: ->(options) { ->(i) { options[:poll_sleep_amount] = i } }
|
40
|
-
},
|
41
|
-
{
|
42
|
-
args: ['-l', '--logfile [LOGFILE]', 'Log file name'],
|
43
|
-
callback: ->(options) { ->(l) { options[:logfile] = l } }
|
44
|
-
},
|
45
|
-
{
|
46
|
-
args: ['-F', '--logformat [LOGFORMAT]', 'Log output format'],
|
47
|
-
callback: ->(options) { ->(f) { options[:logformat] = f } }
|
48
|
-
},
|
49
|
-
{
|
50
|
-
args: ['-P', '--pidfile [PIDFILE]', 'PID file name'],
|
51
|
-
callback: ->(options) { ->(p) { options[:pidfile] = p } }
|
52
|
-
},
|
53
|
-
{
|
54
|
-
args: ['-q', '--quiet', 'Run with minimal output [QUIET] (or [MUTE])'],
|
55
|
-
callback: ->(options) { ->(q) { options[:mute] = q } }
|
56
|
-
},
|
57
|
-
{
|
58
|
-
args: ['-v', '--verbose', 'Run with verbose output [VERBOSE]'],
|
59
|
-
callback: ->(options) { ->(v) { options[:verbose] = v } }
|
60
|
-
}
|
61
|
-
].freeze
|
62
|
-
|
63
|
-
def self.run!(argv = ARGV, env = ENV)
|
64
|
-
new(argv, env).run!
|
65
|
-
end
|
66
|
-
|
67
|
-
def initialize(argv = ARGV, env = ENV)
|
68
|
-
@argv = argv
|
69
|
-
@env = env
|
70
|
-
end
|
71
|
-
|
72
|
-
def run!
|
73
|
-
pre_run
|
74
|
-
run_forever
|
75
|
-
end
|
76
|
-
|
77
|
-
def pre_run
|
78
|
-
parse_options
|
79
|
-
pre_setup
|
80
|
-
setup_env
|
81
|
-
end
|
82
|
-
|
83
|
-
def parse_options
|
84
|
-
OptionParser.new do |opts|
|
85
|
-
opts.banner = BANNER
|
86
|
-
OPTIONS.each do |opt|
|
87
|
-
opts.on(*opt[:args], &(opt[:callback].call(options)))
|
88
|
-
end
|
89
|
-
end.parse!(argv.dup)
|
90
|
-
end
|
91
|
-
|
92
|
-
def pre_setup
|
93
|
-
if options[:initializer_path]
|
94
|
-
load options[:initializer_path].to_s.strip
|
95
|
-
else
|
96
|
-
false
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
def setup_env
|
101
|
-
require 'resque'
|
102
|
-
require 'resque/scheduler'
|
103
|
-
|
104
|
-
# Need to set this here for conditional Process.daemon redirect of
|
105
|
-
# stderr/stdout to /dev/null
|
106
|
-
Resque::Scheduler.mute = !!options[:mute]
|
107
|
-
|
108
|
-
if options[:background]
|
109
|
-
unless Process.respond_to?('daemon')
|
110
|
-
abort 'background option is set, which requires ruby >= 1.9'
|
111
|
-
end
|
112
|
-
|
113
|
-
Process.daemon(true, !Resque::Scheduler.mute)
|
114
|
-
Resque.redis.client.reconnect
|
115
|
-
end
|
116
|
-
|
117
|
-
File.open(options[:pidfile], 'w') do |f|
|
118
|
-
f.puts $PROCESS_ID
|
119
|
-
end if options[:pidfile]
|
120
|
-
|
121
|
-
Resque::Scheduler.configure do |c|
|
122
|
-
# These settings are somewhat redundant given the defaults present
|
123
|
-
# in the attr reader methods. They are left here for clarity and
|
124
|
-
# to serve as an example of how to use `.configure`.
|
125
|
-
|
126
|
-
c.app_name = options[:app_name]
|
127
|
-
c.dynamic = !!options[:dynamic]
|
128
|
-
c.env = options[:env]
|
129
|
-
c.logfile = options[:logfile]
|
130
|
-
c.logformat = options[:logformat]
|
131
|
-
c.poll_sleep_amount = Float(options[:poll_sleep_amount] || '5')
|
132
|
-
c.verbose = !!options[:verbose]
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
def run_forever
|
137
|
-
Resque::Scheduler.run
|
138
|
-
end
|
139
|
-
|
140
|
-
private
|
141
|
-
|
142
|
-
attr_reader :argv, :env
|
143
|
-
|
144
|
-
def options
|
145
|
-
@options ||= {
|
146
|
-
app_name: env['APP_NAME'],
|
147
|
-
background: env['BACKGROUND'],
|
148
|
-
dynamic: env['DYNAMIC_SCHEDULE'],
|
149
|
-
env: env['RAILS_ENV'],
|
150
|
-
initializer_path: env['INITIALIZER_PATH'],
|
151
|
-
logfile: env['LOGFILE'],
|
152
|
-
logformat: env['LOGFORMAT'],
|
153
|
-
mute: env['MUTE'] || env['QUIET'],
|
154
|
-
pidfile: env['PIDFILE'],
|
155
|
-
poll_sleep_amount: env['RESQUE_SCHEDULER_INTERVAL'],
|
156
|
-
verbose: env['VERBOSE']
|
157
|
-
}
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
# vim:fileencoding=utf-8
|
2
|
-
|
3
|
-
module ResqueScheduler
|
4
|
-
# Just builds a logger, with specified verbosity and destination.
|
5
|
-
# The simplest example:
|
6
|
-
#
|
7
|
-
# ResqueScheduler::LoggerBuilder.new.build
|
8
|
-
class LoggerBuilder
|
9
|
-
# Initializes new instance of the builder
|
10
|
-
#
|
11
|
-
# Pass :opts Hash with
|
12
|
-
# - :mute if logger needs to be silent for all levels. Default - false
|
13
|
-
# - :verbose if there is a need in debug messages. Default - false
|
14
|
-
# - :log_dev to output logs into a desired file. Default - STDOUT
|
15
|
-
# - :format log format, either 'text' or 'json'. Default - 'text'
|
16
|
-
#
|
17
|
-
# Example:
|
18
|
-
#
|
19
|
-
# LoggerBuilder.new(
|
20
|
-
# :mute => false, :verbose => true, :log_dev => 'log/scheduler.log'
|
21
|
-
# )
|
22
|
-
def initialize(opts={})
|
23
|
-
@muted = !!opts[:mute]
|
24
|
-
@verbose = !!opts[:verbose]
|
25
|
-
@log_dev = opts[:log_dev] || $stdout
|
26
|
-
@format = opts[:format] || 'text'
|
27
|
-
end
|
28
|
-
|
29
|
-
# Returns an instance of Logger
|
30
|
-
def build
|
31
|
-
logger = Logger.new(@log_dev)
|
32
|
-
logger.level = level
|
33
|
-
logger.formatter = send(:"#{@format}_formatter")
|
34
|
-
logger
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def level
|
40
|
-
if @verbose && !@muted
|
41
|
-
Logger::DEBUG
|
42
|
-
elsif !@muted
|
43
|
-
Logger::INFO
|
44
|
-
else
|
45
|
-
Logger::FATAL
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def text_formatter
|
50
|
-
proc do |severity, datetime, progname, msg|
|
51
|
-
"resque-scheduler: [#{severity}] #{datetime.iso8601}: #{msg}\n"
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def json_formatter
|
56
|
-
proc do |severity, datetime, progname, msg|
|
57
|
-
require 'json'
|
58
|
-
JSON.dump(
|
59
|
-
{
|
60
|
-
:name => 'resque-scheduler',
|
61
|
-
:progname => progname,
|
62
|
-
:level => severity,
|
63
|
-
:timestamp => datetime.iso8601,
|
64
|
-
:msg => msg
|
65
|
-
}
|
66
|
-
) + "\n"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module ResqueScheduler
|
2
|
-
module Plugin
|
3
|
-
extend self
|
4
|
-
def hooks(job, pattern)
|
5
|
-
job.methods.grep(/^#{pattern}/).sort
|
6
|
-
end
|
7
|
-
|
8
|
-
def run_hooks(job, pattern, *args)
|
9
|
-
results = hooks(job, pattern).collect do |hook|
|
10
|
-
job.send(hook, *args)
|
11
|
-
end
|
12
|
-
|
13
|
-
results.all? { |result| result != false }
|
14
|
-
end
|
15
|
-
|
16
|
-
def run_before_delayed_enqueue_hooks(klass, *args)
|
17
|
-
run_hooks(klass, 'before_delayed_enqueue', *args)
|
18
|
-
end
|
19
|
-
|
20
|
-
def run_before_schedule_hooks(klass, *args)
|
21
|
-
run_hooks(klass, 'before_schedule', *args)
|
22
|
-
end
|
23
|
-
|
24
|
-
def run_after_schedule_hooks(klass, *args)
|
25
|
-
run_hooks(klass, 'after_schedule', *args)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
<h1>Schedule</h1>
|
2
|
-
|
3
|
-
<p class='intro'>
|
4
|
-
The list below contains all scheduled jobs. Click "Queue now" to queue
|
5
|
-
a job immediately.
|
6
|
-
Server local time: <%= Time.now %>
|
7
|
-
</p>
|
8
|
-
|
9
|
-
<table>
|
10
|
-
<tr>
|
11
|
-
<th></th>
|
12
|
-
<th>Name</th>
|
13
|
-
<th>Description</th>
|
14
|
-
<th>Interval</th>
|
15
|
-
<th>Class</th>
|
16
|
-
<th>Queue</th>
|
17
|
-
<th>Arguments</th>
|
18
|
-
</tr>
|
19
|
-
<% Resque.schedule.keys.sort.each do |name| %>
|
20
|
-
<% config = Resque.schedule[name] %>
|
21
|
-
<tr>
|
22
|
-
<td style="padding-top: 12px; padding-bottom: 2px; width: 10px">
|
23
|
-
<form action="<%= u "/schedule/requeue" %>" method="post" style="margin-left: 0">
|
24
|
-
<input type="hidden" name="job_name" value="<%= h name %>">
|
25
|
-
<input type="submit" value="Queue now">
|
26
|
-
</form>
|
27
|
-
</td>
|
28
|
-
<td><%= h name %></td>
|
29
|
-
<td><%= h config['description'] %></td>
|
30
|
-
<td style="white-space:nowrap"><%= h schedule_interval(config) %></td>
|
31
|
-
<td><%= h schedule_class(config) %></td>
|
32
|
-
<td><%= h config['queue'] || queue_from_class_name(config['class']) %></td>
|
33
|
-
<td><%= h config['args'].inspect %></td>
|
34
|
-
</tr>
|
35
|
-
<% end %>
|
36
|
-
</table>
|
@@ -1,182 +0,0 @@
|
|
1
|
-
require 'resque_scheduler'
|
2
|
-
require 'resque/server'
|
3
|
-
require 'json'
|
4
|
-
|
5
|
-
# Extend Resque::Server to add tabs
|
6
|
-
module ResqueScheduler
|
7
|
-
module Server
|
8
|
-
def self.included(base)
|
9
|
-
base.class_eval do
|
10
|
-
helpers do
|
11
|
-
def format_time(t)
|
12
|
-
t.strftime('%Y-%m-%d %H:%M:%S %z')
|
13
|
-
end
|
14
|
-
|
15
|
-
def queue_from_class_name(class_name)
|
16
|
-
Resque.queue_from_class(ResqueScheduler::Util.constantize(class_name))
|
17
|
-
end
|
18
|
-
|
19
|
-
def find_job(worker)
|
20
|
-
worker = worker.downcase
|
21
|
-
results = Array.new
|
22
|
-
|
23
|
-
# Check working jobs
|
24
|
-
working = Resque.working
|
25
|
-
working = [working] unless working.is_a?(Array)
|
26
|
-
work = working.select do |w|
|
27
|
-
w.job && w.job["payload"] && w.job['payload']['class'].downcase.include?(worker)
|
28
|
-
end
|
29
|
-
work.each do |w|
|
30
|
-
results += [w.job['payload'].merge({'queue' => w.job['queue'], 'where_at' => 'working'})]
|
31
|
-
end
|
32
|
-
|
33
|
-
# Check delayed Jobs
|
34
|
-
dels = Array.new
|
35
|
-
Resque.delayed_queue_peek(0, Resque.delayed_queue_schedule_size).each do |d|
|
36
|
-
Resque.delayed_timestamp_peek(d, 0, Resque.delayed_timestamp_size(d)).each do |j|
|
37
|
-
dels << j.merge!({'timestamp' => d})
|
38
|
-
end
|
39
|
-
end
|
40
|
-
results += dels.select do |j|
|
41
|
-
j['class'].downcase.include?(worker) && j.merge!({'where_at' => 'delayed'})
|
42
|
-
end
|
43
|
-
|
44
|
-
# Check Queues
|
45
|
-
Resque.queues.each do |queue|
|
46
|
-
queued = Resque.peek(queue, 0, Resque.size(queue))
|
47
|
-
queued = [queued] unless queued.is_a?(Array)
|
48
|
-
results += queued.select do |j|
|
49
|
-
j['class'].downcase.include?(worker) && j.merge!({'queue' => queue, 'where_at' => 'queued'})
|
50
|
-
end
|
51
|
-
end
|
52
|
-
results
|
53
|
-
end
|
54
|
-
|
55
|
-
def schedule_interval(config)
|
56
|
-
if config['every']
|
57
|
-
schedule_interval_every(config['every'])
|
58
|
-
elsif config['cron']
|
59
|
-
'cron: ' + config['cron'].to_s
|
60
|
-
else
|
61
|
-
'Not currently scheduled'
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def schedule_interval_every(every)
|
66
|
-
s = 'every: '
|
67
|
-
if every.respond_to?(:first)
|
68
|
-
s << every.first
|
69
|
-
else
|
70
|
-
s << every
|
71
|
-
end
|
72
|
-
|
73
|
-
return s unless every.respond_to?(:last) && every.length > 1
|
74
|
-
|
75
|
-
s << ' ('
|
76
|
-
meta = every.last.map do |key, value|
|
77
|
-
"#{key.to_s.gsub(/_/, ' ')} #{value}"
|
78
|
-
end
|
79
|
-
s << meta.join(', ') << ')'
|
80
|
-
end
|
81
|
-
|
82
|
-
def schedule_class(config)
|
83
|
-
if config['class'].nil? && !config['custom_job_class'].nil?
|
84
|
-
config['custom_job_class']
|
85
|
-
else
|
86
|
-
config['class']
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
get "/schedule" do
|
92
|
-
Resque.reload_schedule! if Resque::Scheduler.dynamic
|
93
|
-
# Is there a better way to specify alternate template locations with sinatra?
|
94
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/scheduler.erb'))
|
95
|
-
end
|
96
|
-
|
97
|
-
post "/schedule/requeue" do
|
98
|
-
@job_name = params['job_name'] || params[:job_name]
|
99
|
-
config = Resque.schedule[@job_name]
|
100
|
-
@parameters = config['parameters'] || config[:parameters]
|
101
|
-
if @parameters
|
102
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/requeue-params.erb'))
|
103
|
-
else
|
104
|
-
Resque::Scheduler.enqueue_from_config(config)
|
105
|
-
redirect u("/overview")
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
post "/schedule/requeue_with_params" do
|
110
|
-
job_name = params['job_name'] || params[:job_name]
|
111
|
-
config = Resque.schedule[job_name]
|
112
|
-
# Build args hash from post data (removing the job name)
|
113
|
-
submitted_args = params.reject {|key, value| key == 'job_name' || key == :job_name}
|
114
|
-
|
115
|
-
# Merge constructed args hash with existing args hash for
|
116
|
-
# the job, if it exists
|
117
|
-
config_args = config['args'] || config[:args] || {}
|
118
|
-
config_args = config_args.merge(submitted_args)
|
119
|
-
|
120
|
-
# Insert the args hash into config and queue the resque job
|
121
|
-
config = config.merge('args' => config_args)
|
122
|
-
Resque::Scheduler.enqueue_from_config(config)
|
123
|
-
redirect u("/overview")
|
124
|
-
end
|
125
|
-
|
126
|
-
get "/delayed" do
|
127
|
-
# Is there a better way to specify alternate template locations with sinatra?
|
128
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/delayed.erb'))
|
129
|
-
end
|
130
|
-
|
131
|
-
get "/delayed/jobs/:klass" do
|
132
|
-
begin
|
133
|
-
klass = ResqueScheduler::Util::constantize(params[:klass])
|
134
|
-
@args = JSON.load(URI.decode(params[:args]))
|
135
|
-
@timestamps = Resque.scheduled_at(klass, *@args)
|
136
|
-
rescue => err
|
137
|
-
@timestamps = []
|
138
|
-
end
|
139
|
-
|
140
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/delayed_schedules.erb'))
|
141
|
-
end
|
142
|
-
|
143
|
-
post "/delayed/search" do
|
144
|
-
# Is there a better way to specify alternate template locations with sinatra?
|
145
|
-
@jobs = find_job(params[:search])
|
146
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/search.erb'))
|
147
|
-
end
|
148
|
-
|
149
|
-
get "/delayed/:timestamp" do
|
150
|
-
# Is there a better way to specify alternate template locations with sinatra?
|
151
|
-
erb File.read(File.join(File.dirname(__FILE__), 'server/views/delayed_timestamp.erb'))
|
152
|
-
end
|
153
|
-
|
154
|
-
post "/delayed/queue_now" do
|
155
|
-
timestamp = params['timestamp']
|
156
|
-
Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp.to_i) if timestamp.to_i > 0
|
157
|
-
redirect u("/overview")
|
158
|
-
end
|
159
|
-
|
160
|
-
post "/delayed/cancel_now" do
|
161
|
-
klass = ResqueScheduler::Util.constantize params['klass']
|
162
|
-
timestamp = params['timestamp']
|
163
|
-
args = Resque.decode params['args']
|
164
|
-
Resque.remove_delayed_job_from_timestamp(timestamp, klass, *args)
|
165
|
-
redirect u("/delayed")
|
166
|
-
end
|
167
|
-
|
168
|
-
post "/delayed/clear" do
|
169
|
-
Resque.reset_delayed_queue
|
170
|
-
redirect u('delayed')
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
Resque::Server.tabs << 'Schedule'
|
178
|
-
Resque::Server.tabs << 'Delayed'
|
179
|
-
|
180
|
-
Resque::Server.class_eval do
|
181
|
-
include ResqueScheduler::Server
|
182
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module ResqueScheduler
|
2
|
-
class Util
|
3
|
-
# In order to upgrade to resque(1.25) which has deprecated following methods ,
|
4
|
-
# we just added these usefull helpers back to use in Resque Scheduler.
|
5
|
-
# refer to: https://github.com/resque/resque-scheduler/pull/273
|
6
|
-
|
7
|
-
def self.constantize(camel_cased_word)
|
8
|
-
camel_cased_word = camel_cased_word.to_s
|
9
|
-
|
10
|
-
if camel_cased_word.include?('-')
|
11
|
-
camel_cased_word = classify(camel_cased_word)
|
12
|
-
end
|
13
|
-
|
14
|
-
names = camel_cased_word.split('::')
|
15
|
-
names.shift if names.empty? || names.first.empty?
|
16
|
-
|
17
|
-
constant = Object
|
18
|
-
names.each do |name|
|
19
|
-
args = Module.method(:const_get).arity != 1 ? [false] : []
|
20
|
-
|
21
|
-
if constant.const_defined?(name, *args)
|
22
|
-
constant = constant.const_get(name)
|
23
|
-
else
|
24
|
-
constant = constant.const_missing(name)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
constant
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.classify(dashed_word)
|
31
|
-
dashed_word.split('-').each { |part| part[0] = part[0].chr.upcase }.join
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|