resque-scheduler-web 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
|