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.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +48 -0
  7. data/Rakefile +2 -0
  8. data/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb +55 -0
  9. data/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb +62 -0
  10. data/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb +11 -0
  11. data/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb +53 -0
  12. data/app/models/resque_web/plugins/resque_scheduler/job_finder/working_job_finder.rb +40 -0
  13. data/app/models/resque_web/plugins/resque_scheduler/job_finder.rb +81 -0
  14. data/app/views/resque_web/plugins/resque_scheduler/delayed/_next_more.erb +23 -0
  15. data/app/views/resque_web/plugins/resque_scheduler/delayed/_search_form.erb +8 -0
  16. data/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb +61 -0
  17. data/app/views/resque_web/plugins/resque_scheduler/delayed/jobs_klass.erb +20 -0
  18. data/app/views/resque_web/plugins/resque_scheduler/delayed/search.erb +72 -0
  19. data/app/views/resque_web/plugins/resque_scheduler/delayed/timestamp.erb +25 -0
  20. data/app/views/resque_web/plugins/resque_scheduler/schedules/index.html.erb +51 -0
  21. data/app/views/resque_web/plugins/resque_scheduler/schedules/requeue-params.erb +23 -0
  22. data/lib/resque/scheduler/web/version.rb +7 -0
  23. data/lib/resque/scheduler/web.rb +6 -0
  24. data/lib/resque_web/plugins/resque_scheduler/engine.rb +49 -0
  25. data/resque-scheduler-web.gemspec +35 -0
  26. data/spec/controllers/delayed_controller_spec.rb +117 -0
  27. data/spec/controllers/schedules_controller_spec.rb +152 -0
  28. data/spec/dummy/README.rdoc +28 -0
  29. data/spec/dummy/Rakefile +7 -0
  30. data/spec/dummy/app/assets/images/.keep +0 -0
  31. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  32. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  33. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  34. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  35. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  36. data/spec/dummy/app/mailers/.keep +0 -0
  37. data/spec/dummy/app/models/.keep +0 -0
  38. data/spec/dummy/app/models/concerns/.keep +0 -0
  39. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  40. data/spec/dummy/bin/bundle +3 -0
  41. data/spec/dummy/bin/rails +4 -0
  42. data/spec/dummy/bin/rake +4 -0
  43. data/spec/dummy/bin/setup +29 -0
  44. data/spec/dummy/config/application.rb +31 -0
  45. data/spec/dummy/config/boot.rb +5 -0
  46. data/spec/dummy/config/database.yml +25 -0
  47. data/spec/dummy/config/environment.rb +5 -0
  48. data/spec/dummy/config/environments/development.rb +42 -0
  49. data/spec/dummy/config/environments/production.rb +83 -0
  50. data/spec/dummy/config/environments/test.rb +43 -0
  51. data/spec/dummy/config/initializers/assets.rb +12 -0
  52. data/spec/dummy/config/initializers/backtrace_silencers.rb +9 -0
  53. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  54. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  55. data/spec/dummy/config/initializers/inflections.rb +16 -0
  56. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  57. data/spec/dummy/config/initializers/session_store.rb +3 -0
  58. data/spec/dummy/config/initializers/wrap_parameters.rb +15 -0
  59. data/spec/dummy/config/locales/en.yml +23 -0
  60. data/spec/dummy/config/routes.rb +3 -0
  61. data/spec/dummy/config/secrets.yml +22 -0
  62. data/spec/dummy/config.ru +4 -0
  63. data/spec/dummy/db/development.sqlite3 +0 -0
  64. data/spec/dummy/db/schema.rb +18 -0
  65. data/spec/dummy/db/test.sqlite3 +0 -0
  66. data/spec/dummy/lib/assets/.keep +0 -0
  67. data/spec/dummy/log/.keep +0 -0
  68. data/spec/dummy/log/development.log +4 -0
  69. data/spec/dummy/log/test.log +56454 -0
  70. data/spec/dummy/public/404.html +67 -0
  71. data/spec/dummy/public/422.html +67 -0
  72. data/spec/dummy/public/500.html +66 -0
  73. data/spec/dummy/public/favicon.ico +0 -0
  74. data/spec/features/navigation_spec.rb +16 -0
  75. data/spec/features/schedules/requeuing_a_job_with_parameters_spec.rb +36 -0
  76. data/spec/features/schedules/scheduled_jobs_page_spec.rb +80 -0
  77. data/spec/models/job_finder/working_job_finder_spec.rb +38 -0
  78. data/spec/models/job_finder_spec.rb +68 -0
  79. data/spec/rails_helper.rb +25 -0
  80. data/spec/routing/delayed_routing_spec.rb +9 -0
  81. data/spec/spec_helper.rb +96 -0
  82. data/spec/support/redis_instance.rb +133 -0
  83. data/spec/support/test_jobs.rb +77 -0
  84. 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
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in resque-scheduler-web.gemspec
4
+ gemspec
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,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -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,11 @@
1
+ module ResqueWeb
2
+ module Plugins
3
+ module ResqueScheduler
4
+ module DelayedHelper
5
+ def format_time(t)
6
+ t.strftime('%Y-%m-%d %H:%M:%S %z')
7
+ end
8
+ end
9
+ end
10
+ end
11
+ 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'>&laquo;
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 &raquo;</a>
21
+ <% end %>
22
+ </p>
23
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <form method="POST" action="<%= delayed_search_path %>">
2
+ <input type='input' name='search' value="<%= params[:search] %>"/>
3
+ <input type='submit' value='Search'/>
4
+ </form>
5
+
6
+
7
+
8
+
@@ -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
+