resque-scheduler-web 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+