resque-scheduler-web 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +48 -0
- data/Rakefile +2 -0
- data/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb +55 -0
- data/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb +62 -0
- data/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb +11 -0
- data/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb +53 -0
- data/app/models/resque_web/plugins/resque_scheduler/job_finder/working_job_finder.rb +40 -0
- data/app/models/resque_web/plugins/resque_scheduler/job_finder.rb +81 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/_next_more.erb +23 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb +8 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb +61 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb +20 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb +72 -0
- data/app/views/resque_web/plugins/resque_scheduler/delayed/timestamp.erb +25 -0
- data/app/views/resque_web/plugins/resque_scheduler/schedules/index.html.erb +51 -0
- data/app/views/resque_web/plugins/resque_scheduler/schedules/requeue-params.erb +23 -0
- data/lib/resque/scheduler/web/version.rb +7 -0
- data/lib/resque/scheduler/web.rb +6 -0
- data/lib/resque_web/plugins/resque_scheduler/engine.rb +49 -0
- data/resque-scheduler-web.gemspec +35 -0
- data/spec/controllers/delayed_controller_spec.rb +117 -0
- data/spec/controllers/schedules_controller_spec.rb +152 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/images/.keep +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/concerns/.keep +0 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.keep +0 -0
- data/spec/dummy/app/models/.keep +0 -0
- data/spec/dummy/app/models/concerns/.keep +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config/application.rb +31 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +42 -0
- data/spec/dummy/config/environments/production.rb +83 -0
- data/spec/dummy/config/environments/test.rb +43 -0
- data/spec/dummy/config/initializers/assets.rb +12 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +15 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +18 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/lib/assets/.keep +0 -0
- data/spec/dummy/log/.keep +0 -0
- data/spec/dummy/log/development.log +4 -0
- data/spec/dummy/log/test.log +56454 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/features/navigation_spec.rb +16 -0
- data/spec/features/schedules/requeuing_a_job_with_parameters_spec.rb +36 -0
- data/spec/features/schedules/scheduled_jobs_page_spec.rb +80 -0
- data/spec/models/job_finder/working_job_finder_spec.rb +38 -0
- data/spec/models/job_finder_spec.rb +68 -0
- data/spec/rails_helper.rb +25 -0
- data/spec/routing/delayed_routing_spec.rb +9 -0
- data/spec/spec_helper.rb +96 -0
- data/spec/support/redis_instance.rb +133 -0
- data/spec/support/test_jobs.rb +77 -0
- metadata +312 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1e03854b76a62075cb549985fff801655ebea3d5
|
4
|
+
data.tar.gz: c17f6ae62c750215da4aa0a57985a4187f7ff354
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7a869d83a46db7b6e5e66e0090f0d54cc2fb5e61772b4512043e5c74ba486a729fb03ce775aa8eddf563e936aca433cc1847f4bcf2efd5c8f76c25cd5df84dd8
|
7
|
+
data.tar.gz: b3a62b9f4cde28c559480b9aa452a4ab3ef8b984923d02417b01e66749a8aa7b734ced4949f8ba468018b83e339d1325ca71ff1592aa691dd9143d333dd1890f
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/dummy/log
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Matt Gibson
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# Resque::Scheduler::Web
|
2
|
+
|
3
|
+
This gem provides tabs in [Resque Web](https://github.com/resque/resque-web)
|
4
|
+
for managing [Resque Scheduler](https://github.com/resque/resque-scheduler). It uses the
|
5
|
+
new Rails Engine approach, rather than the old Sinatra one.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'resque-scheduler-web'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install resque-scheduler-web
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
The gem will automatically add the correct tabs, provided you have the Resque
|
24
|
+
Web engine mounted like this in routes.rb:
|
25
|
+
|
26
|
+
mount ResqueWeb::Engine => 'admin/resque_web'
|
27
|
+
|
28
|
+
## Running the tests
|
29
|
+
|
30
|
+
cd resque-scheduler-web
|
31
|
+
bundle exec rspec spec
|
32
|
+
|
33
|
+
|
34
|
+
## Contributing
|
35
|
+
|
36
|
+
1. Fork it ( https://github.com/mattgibson/resque-scheduler-web/fork )
|
37
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
38
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
39
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
40
|
+
5. Create a new Pull Request
|
41
|
+
|
42
|
+
|
43
|
+
## Acknowledgements
|
44
|
+
|
45
|
+
The original code and tests for this gem were taken from the Resque Scheduler gem's
|
46
|
+
Sinatra interface, and subsequently adapted into a Rails engine. Kudos and
|
47
|
+
thanks to the [original](https://github.com/resque/resque-scheduler/commits/master/lib/resque/scheduler/server.rb)
|
48
|
+
[authors](https://github.com/resque/resque-scheduler/commits/e0e91aa238c51db12794755430a7411c6ad1bfca/lib/resque_scheduler/server.rb).
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
module ResqueWeb
|
2
|
+
module Plugins
|
3
|
+
module ResqueScheduler
|
4
|
+
# Controller for delayed jobs. These have been added to the queue by the
|
5
|
+
# application, so here, they can be run immediately, deleted from the
|
6
|
+
# queue, or rescheduled.
|
7
|
+
class DelayedController < ResqueWeb::ApplicationController
|
8
|
+
def index
|
9
|
+
@start = params[:start].to_i
|
10
|
+
@number_to_show = 20
|
11
|
+
@total_number_of_delayed_jobs = Resque.delayed_queue_schedule_size
|
12
|
+
@timestamps = Resque.delayed_queue_peek(@start, @number_to_show)
|
13
|
+
end
|
14
|
+
|
15
|
+
def jobs_klass
|
16
|
+
klass = Resque::Scheduler::Util.constantize(params[:klass])
|
17
|
+
@args = JSON.load(URI.decode(params[:args]))
|
18
|
+
@timestamps = Resque.scheduled_at(klass, *@args)
|
19
|
+
rescue
|
20
|
+
@timestamps = []
|
21
|
+
end
|
22
|
+
|
23
|
+
def search
|
24
|
+
@jobs = JobFinder.new(params[:search]).find_jobs
|
25
|
+
end
|
26
|
+
|
27
|
+
def cancel_now
|
28
|
+
klass = Resque::Scheduler::Util.constantize(params['klass'])
|
29
|
+
timestamp = params['timestamp']
|
30
|
+
args = Resque.decode params['args']
|
31
|
+
Resque.remove_delayed_job_from_timestamp(timestamp, klass, *args)
|
32
|
+
redirect_to Engine.app.url_helpers.delayed_path
|
33
|
+
end
|
34
|
+
|
35
|
+
def clear
|
36
|
+
Resque.reset_delayed_queue
|
37
|
+
redirect_to Engine.app.url_helpers.delayed_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def queue_now
|
41
|
+
timestamp = params['timestamp'].to_i
|
42
|
+
if timestamp > 0
|
43
|
+
Resque::Scheduler.enqueue_delayed_items_for_timestamp(timestamp)
|
44
|
+
end
|
45
|
+
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
|
46
|
+
end
|
47
|
+
|
48
|
+
def timestamp
|
49
|
+
@timestamp = params[:timestamp].to_i
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'resque/scheduler/server'
|
2
|
+
|
3
|
+
module ResqueWeb
|
4
|
+
module Plugins
|
5
|
+
module ResqueScheduler
|
6
|
+
class SchedulesController < ResqueWeb::ApplicationController
|
7
|
+
|
8
|
+
include Resque::Scheduler::Server::HelperMethods
|
9
|
+
|
10
|
+
def index
|
11
|
+
Resque.reload_schedule! if Resque::Scheduler.dynamic
|
12
|
+
jobs_in_this_env = Resque.schedule.select do |name|
|
13
|
+
scheduled_in_this_env?(name)
|
14
|
+
end
|
15
|
+
keys = jobs_in_this_env.keys.sort
|
16
|
+
@scheduled_jobs = keys.inject({}) do |jobs, job_name|
|
17
|
+
jobs.merge(job_name => Resque.schedule[job_name])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def destroy
|
22
|
+
if Resque::Scheduler.dynamic
|
23
|
+
job_name = params['job_name'] || params[:job_name]
|
24
|
+
Resque.remove_schedule(job_name)
|
25
|
+
end
|
26
|
+
redirect_to Engine.app.url_helpers.schedules_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def requeue
|
30
|
+
@job_name = params['job_name'] || params[:job_name]
|
31
|
+
config = Resque.schedule[@job_name]
|
32
|
+
@parameters = config['parameters'] || config[:parameters]
|
33
|
+
if @parameters
|
34
|
+
render 'requeue-params'
|
35
|
+
else
|
36
|
+
Resque::Scheduler.enqueue_from_config(config)
|
37
|
+
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def requeue_with_params
|
42
|
+
job_name = params['job_name'] || params[:job_name]
|
43
|
+
config = Resque.schedule[job_name]
|
44
|
+
# Build args hash from post data (removing the job name)
|
45
|
+
submitted_args = params.reject do |key, _value|
|
46
|
+
%w(job_name action controller).include?(key)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Merge constructed args hash with existing args hash for
|
50
|
+
# the job, if it exists
|
51
|
+
config_args = config['args'] || config[:args] || {}
|
52
|
+
config_args = config_args.merge(submitted_args)
|
53
|
+
|
54
|
+
# Insert the args hash into config and queue the resque job
|
55
|
+
config = config.merge('args' => config_args)
|
56
|
+
Resque::Scheduler.enqueue_from_config(config)
|
57
|
+
redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module ResqueWeb
|
2
|
+
module Plugins
|
3
|
+
module ResqueScheduler
|
4
|
+
module SchedulesHelper
|
5
|
+
def scheduled_in_this_env?(name)
|
6
|
+
return true if Resque.schedule[name]['rails_env'].nil?
|
7
|
+
rails_env(name).split(/[\s,]+/).include?(Resque::Scheduler.env)
|
8
|
+
end
|
9
|
+
|
10
|
+
def rails_env(name)
|
11
|
+
Resque.schedule[name]['rails_env']
|
12
|
+
end
|
13
|
+
|
14
|
+
def schedule_interval_every(every)
|
15
|
+
every = [*every]
|
16
|
+
s = 'every: ' << every.first
|
17
|
+
|
18
|
+
return s unless every.length > 1
|
19
|
+
|
20
|
+
s << ' ('
|
21
|
+
meta = every.last.map do |key, value|
|
22
|
+
"#{key.to_s.gsub(/_/, ' ')} #{value}"
|
23
|
+
end
|
24
|
+
s << meta.join(', ') << ')'
|
25
|
+
end
|
26
|
+
|
27
|
+
def schedule_interval(config)
|
28
|
+
if config['every']
|
29
|
+
schedule_interval_every(config['every'])
|
30
|
+
elsif config['cron']
|
31
|
+
'cron: ' + config['cron'].to_s
|
32
|
+
else
|
33
|
+
'Not currently scheduled'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def schedule_class(config)
|
38
|
+
if config['class'].nil? && !config['custom_job_class'].nil?
|
39
|
+
config['custom_job_class']
|
40
|
+
else
|
41
|
+
config['class']
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def queue_from_class_name(class_name)
|
46
|
+
Resque.queue_from_class(
|
47
|
+
Resque::Scheduler::Util.constantize(class_name)
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module ResqueWeb
|
2
|
+
module Plugins
|
3
|
+
module ResqueScheduler
|
4
|
+
class JobFinder
|
5
|
+
# This class finds working jobs that Resque is currently processing
|
6
|
+
class WorkingJobFinder
|
7
|
+
|
8
|
+
attr_accessor :search_term
|
9
|
+
|
10
|
+
def initialize(search_term)
|
11
|
+
@search_term = search_term
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_jobs
|
15
|
+
workers_with_jobs_that_match_search_term.collect do |w|
|
16
|
+
w.job['payload'].merge(
|
17
|
+
'queue' => w.job['queue'],
|
18
|
+
'where_at' => 'working'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def workers_with_jobs_that_match_search_term
|
24
|
+
all_working_jobs.select do |w|
|
25
|
+
w.job &&
|
26
|
+
w.job['payload'] &&
|
27
|
+
w.job['payload']['class'].downcase.include?(search_term)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def all_working_jobs
|
34
|
+
[*Resque.working]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ResqueWeb
|
2
|
+
module Plugins
|
3
|
+
module ResqueScheduler
|
4
|
+
# This class exists to find jobs which match a search term. They may be
|
5
|
+
# being processed, in the queue, or delayed.
|
6
|
+
class JobFinder
|
7
|
+
|
8
|
+
attr_accessor :search_term
|
9
|
+
|
10
|
+
def initialize(search_term = nil)
|
11
|
+
@search_term = search_term || ''
|
12
|
+
@search_term.downcase!
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_jobs
|
16
|
+
return [] if search_term.empty?
|
17
|
+
results = []
|
18
|
+
results += working_jobs_where_class_name_contains_search_term
|
19
|
+
results += delayed_jobs_where_class_name_contains_search_term
|
20
|
+
results + queued_jobs_where_class_name_matches_search_term
|
21
|
+
end
|
22
|
+
|
23
|
+
def working_jobs_where_class_name_contains_search_term
|
24
|
+
WorkingJobFinder.new(search_term).find_jobs
|
25
|
+
end
|
26
|
+
|
27
|
+
def delayed_jobs_where_class_name_contains_search_term
|
28
|
+
delayed_job_timestamps.inject([]) do |matching_jobs, timestamp|
|
29
|
+
matching_jobs + delayed_jobs_for_timestamp_that_match_search_term(timestamp)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def delayed_jobs_for_timestamp_that_match_search_term(timestamp)
|
34
|
+
delayed_jobs_for_timestamp(timestamp).select do |job|
|
35
|
+
job['class'].downcase.include?(search_term) &&
|
36
|
+
job.merge!('where_at' => 'delayed') &&
|
37
|
+
job.merge!('timestamp' => timestamp)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def delayed_job_timestamps
|
42
|
+
Resque.delayed_queue_peek(0, schedule_size)
|
43
|
+
end
|
44
|
+
|
45
|
+
def schedule_size
|
46
|
+
Resque.delayed_queue_schedule_size
|
47
|
+
end
|
48
|
+
|
49
|
+
def delayed_jobs_for_timestamp(timestamp)
|
50
|
+
Resque.delayed_timestamp_peek(timestamp,
|
51
|
+
0,
|
52
|
+
number_of_delayed_jobs_at(timestamp))
|
53
|
+
end
|
54
|
+
|
55
|
+
def number_of_delayed_jobs_at(timestamp)
|
56
|
+
Resque.delayed_timestamp_size(timestamp)
|
57
|
+
end
|
58
|
+
|
59
|
+
def queued_jobs_where_class_name_matches_search_term
|
60
|
+
Resque.queues.inject([]) do |results, queue|
|
61
|
+
results + queued_jobs_from_queue(queue).select do |job|
|
62
|
+
job['class'].downcase.include?(search_term) &&
|
63
|
+
job.merge!('queue' => queue) &&
|
64
|
+
job.merge!('where_at' => 'queued')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def queued_jobs_from_queue(queue)
|
70
|
+
bits = Resque.peek(queue, 0, Resque.size(queue))
|
71
|
+
if bits.is_a? Array
|
72
|
+
bits
|
73
|
+
else
|
74
|
+
[bits]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<% # per_page was added in 1.23.1; gems which add to resque-server don't pass that variable along so it would crash %>
|
2
|
+
<% # without a default value %>
|
3
|
+
<% per_page ||= 20 %>
|
4
|
+
<% if start - per_page >= 0 || start + per_page <= size %>
|
5
|
+
<p class='pagination'>
|
6
|
+
<% if start + per_page <= size %>
|
7
|
+
<a href="<%= current_page %>?start=<%= start + per_page %>" class='more'>«
|
8
|
+
Next</a>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% (size / per_page.to_f - 1).ceil.downto(0).each do |page_num| %>
|
12
|
+
<% if start == page_num * per_page %>
|
13
|
+
<%= page_num %>
|
14
|
+
<% else %>
|
15
|
+
<a href="<%= current_page %>?start=<%= page_num * per_page %>"> <%= page_num %></a>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% if start - per_page >= 0 %>
|
20
|
+
<a href="<%= current_page %>?start=<%= start - per_page %>" class='less'>Previous »</a>
|
21
|
+
<% end %>
|
22
|
+
</p>
|
23
|
+
<% end %>
|
@@ -0,0 +1,61 @@
|
|
1
|
+
<h1>Delayed Jobs</h1>
|
2
|
+
|
3
|
+
<%= render partial: 'search_form' %>
|
4
|
+
|
5
|
+
<p class='intro'>
|
6
|
+
This list below contains the timestamps for scheduled delayed jobs.
|
7
|
+
Server local time: <%= Time.now %>
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p class='sub'>
|
11
|
+
<% finish = [@start + @number_to_show, @total_number_of_delayed_jobs].min %>
|
12
|
+
Showing <%= @start %> to <%= finish %> of
|
13
|
+
<b><%= @total_number_of_delayed_jobs %></b> timestamps
|
14
|
+
</p>
|
15
|
+
|
16
|
+
<table class="table table-bordered">
|
17
|
+
<tr>
|
18
|
+
<th></th>
|
19
|
+
<th>Timestamp</th>
|
20
|
+
<th>Job count</th>
|
21
|
+
<th>Class</th>
|
22
|
+
<th>Args</th>
|
23
|
+
<th>All schedules</th>
|
24
|
+
</tr>
|
25
|
+
<% @timestamps.each do |timestamp| %>
|
26
|
+
<tr>
|
27
|
+
<td>
|
28
|
+
<form action="<%= queue_now_path %>" method="post">
|
29
|
+
<input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
|
30
|
+
<input type="submit" value="Queue now" class="btn btn-default">
|
31
|
+
</form>
|
32
|
+
</td>
|
33
|
+
<td><a href="<%= delayed_path timestamp: timestamp %>"><%= format_time(Time.at(timestamp)) %></a></td>
|
34
|
+
<td><%= delayed_timestamp_size = Resque.delayed_timestamp_size(timestamp) %></td>
|
35
|
+
<% job = Resque.delayed_timestamp_peek(timestamp, 0, 1).first %>
|
36
|
+
<td>
|
37
|
+
<% if job && delayed_timestamp_size == 1 %>
|
38
|
+
<%= h(job['class']) %>
|
39
|
+
<% else %>
|
40
|
+
<a href="<%= delayed_path timestamp: timestamp %>">see details</a>
|
41
|
+
<% end %>
|
42
|
+
</td>
|
43
|
+
<td><%= h(job['args'].inspect) if job && delayed_timestamp_size == 1 %></td>
|
44
|
+
<td>
|
45
|
+
<% if job %>
|
46
|
+
<a href="<%= delayed_job_class_path klass: job['class'], args: URI.encode(job['args'].to_json) %>">All schedules</a>
|
47
|
+
<% end %>
|
48
|
+
</td>
|
49
|
+
</tr>
|
50
|
+
<% end %>
|
51
|
+
</table>
|
52
|
+
|
53
|
+
<% if @total_number_of_delayed_jobs > 0 %>
|
54
|
+
<br>
|
55
|
+
<form method="POST" action="<%= clear_path %>" class='clear-delayed'>
|
56
|
+
<input type='submit' name='' value='Clear Delayed Jobs' />
|
57
|
+
</form>
|
58
|
+
<% end %>
|
59
|
+
|
60
|
+
<%= render partial: 'next_more', locals: { :start => @start, :size => @total_number_of_delayed_jobs } %>
|
61
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<h1>Delayed jobs scheduled for <%= params[:klass] %> (<%= @args %>)</h1>
|
2
|
+
|
3
|
+
<table class='jobs'>
|
4
|
+
<tr>
|
5
|
+
<th>Timestamp</th>
|
6
|
+
</tr>
|
7
|
+
|
8
|
+
<% @timestamps.each do |t| %>
|
9
|
+
<tr>
|
10
|
+
<td>
|
11
|
+
<%= Time.at(t) %>
|
12
|
+
</td>
|
13
|
+
</tr>
|
14
|
+
<% end %>
|
15
|
+
<% if @timestamps.empty? %>
|
16
|
+
<tr>
|
17
|
+
<td class='no-data'>There are no such jobs scheduled.</td>
|
18
|
+
</tr>
|
19
|
+
<% end %>
|
20
|
+
</table>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
<h1>Search Results</h1>
|
2
|
+
<%= render partial: 'search_form' %>
|
3
|
+
<hr>
|
4
|
+
<% delayed = @jobs.select { |j| j['where_at'] == 'delayed' } %>
|
5
|
+
<h1>Delayed jobs</h1>
|
6
|
+
<table class="jobs table table-bordered">
|
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="<%= queue_now_path %>" method="post">
|
18
|
+
<input type="hidden" name="timestamp" value="<%= job['timestamp'].to_i %>">
|
19
|
+
<input type="submit" value="Queue now" class="btn btn-default">
|
20
|
+
</form>
|
21
|
+
</td>
|
22
|
+
<td>
|
23
|
+
<form action="<%= cancel_now_path %>" 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="<%= Resque.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 table table-bordered'>
|
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 table table-bordered'>
|
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,25 @@
|
|
1
|
+
<h1>Delayed jobs scheduled for <%= format_time(Time.at(@timestamp)) %></h1>
|
2
|
+
|
3
|
+
<p class='sub'>Showing <%= start = params[:start].to_i %> to <%= start + 20 %> of <b><%=size = Resque.delayed_timestamp_size(@timestamp)%></b> jobs</p>
|
4
|
+
|
5
|
+
<table class='jobs'>
|
6
|
+
<tr>
|
7
|
+
<th>Class</th>
|
8
|
+
<th>Args</th>
|
9
|
+
</tr>
|
10
|
+
<% jobs = Resque.delayed_timestamp_peek(@timestamp, start, 20) %>
|
11
|
+
<% jobs.each do |job| %>
|
12
|
+
<tr>
|
13
|
+
<td class='class'><%= job['class'] %></td>
|
14
|
+
<td class='args'><%=h job['args'].inspect %></td>
|
15
|
+
</tr>
|
16
|
+
<% end %>
|
17
|
+
<% if jobs.empty? %>
|
18
|
+
<tr>
|
19
|
+
<td class='no-data' colspan='2'>There are no pending jobs scheduled for this time.</td>
|
20
|
+
</tr>
|
21
|
+
<% end %>
|
22
|
+
</table>
|
23
|
+
|
24
|
+
<%= render partial: 'next_more', locals: {:start => start, :size => size} %>
|
25
|
+
|