resque-scheduler-web 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -3
  3. data/.rubocop.yml +1 -0
  4. data/.travis.yml +11 -0
  5. data/README.md +8 -2
  6. data/Rakefile +10 -1
  7. data/app/assets/javascripts/resque_web/plugins/resque_scheduler/application.js +0 -0
  8. data/app/assets/stylesheets/resque_web/plugins/resque_scheduler/application.css +3 -0
  9. data/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb +9 -1
  10. data/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb +7 -1
  11. data/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb +9 -0
  12. data/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb +29 -1
  13. data/app/models/resque_web/plugins/resque_scheduler/job_finder.rb +15 -9
  14. data/app/models/resque_web/plugins/resque_scheduler/job_finder/working_job_finder.rb +22 -5
  15. data/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb +1 -1
  16. data/lib/resque/scheduler/web.rb +1 -1
  17. data/lib/resque/scheduler/web/version.rb +1 -1
  18. data/lib/resque_web/plugins/resque_scheduler/engine.rb +10 -6
  19. data/resque-scheduler-web.gemspec +10 -5
  20. data/spec/controllers/delayed_controller_spec.rb +10 -18
  21. data/spec/controllers/schedules_controller_spec.rb +28 -21
  22. data/spec/dummy/app/controllers/application_controller.rb +1 -0
  23. data/spec/dummy/config/application.rb +1 -0
  24. data/spec/dummy/log/test.log +5666 -0
  25. data/spec/features/navigation_spec.rb +1 -2
  26. data/spec/features/schedules/requeuing_a_job_with_parameters_spec.rb +8 -4
  27. data/spec/features/schedules/scheduled_jobs_page_spec.rb +8 -2
  28. data/spec/models/job_finder/working_job_finder_spec.rb +9 -7
  29. data/spec/models/job_finder_spec.rb +16 -13
  30. data/spec/rails_helper.rb +12 -9
  31. data/spec/routing/delayed_routing_spec.rb +5 -3
  32. data/spec/spec_helper.rb +6 -7
  33. data/spec/support/redis_instance.rb +13 -11
  34. data/spec/support/test_jobs.rb +9 -4
  35. metadata +68 -24
  36. data/spec/dummy/app/helpers/application_helper.rb +0 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e03854b76a62075cb549985fff801655ebea3d5
4
- data.tar.gz: c17f6ae62c750215da4aa0a57985a4187f7ff354
3
+ metadata.gz: 117651b5c62bac5f16c145b3f4aa0f6f38f3d9bc
4
+ data.tar.gz: 31af2fd0dc677d3014f097436dc1e7e2c06b577f
5
5
  SHA512:
6
- metadata.gz: 7a869d83a46db7b6e5e66e0090f0d54cc2fb5e61772b4512043e5c74ba486a729fb03ce775aa8eddf563e936aca433cc1847f4bcf2efd5c8f76c25cd5df84dd8
7
- data.tar.gz: b3a62b9f4cde28c559480b9aa452a4ab3ef8b984923d02417b01e66749a8aa7b734ced4949f8ba468018b83e339d1325ca71ff1592aa691dd9143d333dd1890f
6
+ metadata.gz: 7205b8b5e211acac1efc24d102e34fe6cb2f7c0ff5f1a187b608dedb22c7a071577e629b4bf13e8c380e00ec184e4a833455929558d6fb8b240ded5552ec1cec
7
+ data.tar.gz: f70ea78760c27134564163b973f2a900c6ae797f8357526f5bf0bb1abfea5c33fb2a147cf8afa04f6497ce068d7898afa16edabbea8779517d0124fdde72ea14
data/.gitignore CHANGED
@@ -12,9 +12,9 @@ lib/bundler/man
12
12
  pkg
13
13
  rdoc
14
14
  spec/reports
15
- test/tmp
16
- test/dummy/log
17
- test/version_tmp
15
+ spec/tmp
16
+ spec/dummy/log
17
+ spec/version_tmp
18
18
  tmp
19
19
  *.bundle
20
20
  *.so
data/.rubocop.yml ADDED
@@ -0,0 +1 @@
1
+ require: rubocop-rspec
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.2.0
5
+ - 2.1.5
6
+ - 2.0.0
7
+ - 1.9.3
8
+
9
+ addons:
10
+ code_climate:
11
+ repo_token: 854dad5a427f26dc32dcfafd54d1824c8f052a31c4b11fa51b5181334e53a434
data/README.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Resque::Scheduler::Web
2
2
 
3
+ [![Gem Version](https://badge.fury.io/rb/resque-scheduler-web.svg)](http://badge.fury.io/rb/resque-scheduler-web)
4
+ [![Code Climate](https://codeclimate.com/github/mattgibson/resque-scheduler-web/badges/gpa.svg)](https://codeclimate.com/github/mattgibson/resque-scheduler-web)
5
+ [![Test Coverage](https://codeclimate.com/github/mattgibson/resque-scheduler-web/badges/coverage.svg)](https://codeclimate.com/github/mattgibson/resque-scheduler-web)
6
+ [![Inline docs](http://inch-ci.org/github/mattgibson/resque-scheduler-web.svg?branch=master)](http://inch-ci.org/github/mattgibson/resque-scheduler-web)
7
+ [![Dependency Status](https://gemnasium.com/mattgibson/resque-scheduler-web.svg)](https://gemnasium.com/mattgibson/resque-scheduler-web)
8
+ [![Build Status](https://travis-ci.org/mattgibson/resque-scheduler-web.svg?branch=master)](https://travis-ci.org/mattgibson/resque-scheduler-web)
9
+
3
10
  This gem provides tabs in [Resque Web](https://github.com/resque/resque-web)
4
11
  for managing [Resque Scheduler](https://github.com/resque/resque-scheduler). It uses the
5
12
  new Rails Engine approach, rather than the old Sinatra one.
@@ -28,8 +35,7 @@ Web engine mounted like this in routes.rb:
28
35
  ## Running the tests
29
36
 
30
37
  cd resque-scheduler-web
31
- bundle exec rspec spec
32
-
38
+ bundle exec rake
33
39
 
34
40
  ## Contributing
35
41
 
data/Rakefile CHANGED
@@ -1,2 +1,11 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
 
3
+ begin
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+ rescue LoadError
10
+ puts 'RSpec is not installed!'
11
+ end
@@ -0,0 +1,3 @@
1
+ .container form {
2
+ margin-top: 0;
3
+ }
@@ -5,6 +5,7 @@ module ResqueWeb
5
5
  # application, so here, they can be run immediately, deleted from the
6
6
  # queue, or rescheduled.
7
7
  class DelayedController < ResqueWeb::ApplicationController
8
+ # GET /delayed
8
9
  def index
9
10
  @start = params[:start].to_i
10
11
  @number_to_show = 20
@@ -12,6 +13,9 @@ module ResqueWeb
12
13
  @timestamps = Resque.delayed_queue_peek(@start, @number_to_show)
13
14
  end
14
15
 
16
+ # GET /delayed/jobs/:klass
17
+ # Shows us all of the jobs of this type, with these args. Accessed by
18
+ # clicking the 'All schedules' link next to a delayed job.
15
19
  def jobs_klass
16
20
  klass = Resque::Scheduler::Util.constantize(params[:klass])
17
21
  @args = JSON.load(URI.decode(params[:args]))
@@ -20,10 +24,12 @@ module ResqueWeb
20
24
  @timestamps = []
21
25
  end
22
26
 
27
+ # POST /delayed/search
23
28
  def search
24
29
  @jobs = JobFinder.new(params[:search]).find_jobs
25
30
  end
26
31
 
32
+ # POST /delayed/cancel_now
27
33
  def cancel_now
28
34
  klass = Resque::Scheduler::Util.constantize(params['klass'])
29
35
  timestamp = params['timestamp']
@@ -32,11 +38,13 @@ module ResqueWeb
32
38
  redirect_to Engine.app.url_helpers.delayed_path
33
39
  end
34
40
 
41
+ # POST /delayed/clear
35
42
  def clear
36
43
  Resque.reset_delayed_queue
37
44
  redirect_to Engine.app.url_helpers.delayed_path
38
45
  end
39
46
 
47
+ # POST /delayed/queue_now
40
48
  def queue_now
41
49
  timestamp = params['timestamp'].to_i
42
50
  if timestamp > 0
@@ -45,10 +53,10 @@ module ResqueWeb
45
53
  redirect_to ResqueWeb::Engine.app.url_helpers.overview_path
46
54
  end
47
55
 
56
+ # GET /delayed/:timestamp
48
57
  def timestamp
49
58
  @timestamp = params[:timestamp].to_i
50
59
  end
51
-
52
60
  end
53
61
  end
54
62
  end
@@ -3,10 +3,13 @@ require 'resque/scheduler/server'
3
3
  module ResqueWeb
4
4
  module Plugins
5
5
  module ResqueScheduler
6
+ # Controller for the schedule. If it is dynamic, then the actions allow
7
+ # the jobs to be destroyed. Otherwise, the jobs can be manually queued
8
+ # for immediate execution.
6
9
  class SchedulesController < ResqueWeb::ApplicationController
7
-
8
10
  include Resque::Scheduler::Server::HelperMethods
9
11
 
12
+ # GET /schedule
10
13
  def index
11
14
  Resque.reload_schedule! if Resque::Scheduler.dynamic
12
15
  jobs_in_this_env = Resque.schedule.select do |name|
@@ -18,6 +21,7 @@ module ResqueWeb
18
21
  end
19
22
  end
20
23
 
24
+ # DELETE /schedule
21
25
  def destroy
22
26
  if Resque::Scheduler.dynamic
23
27
  job_name = params['job_name'] || params[:job_name]
@@ -26,6 +30,7 @@ module ResqueWeb
26
30
  redirect_to Engine.app.url_helpers.schedules_path
27
31
  end
28
32
 
33
+ # POST /schedule/requeue
29
34
  def requeue
30
35
  @job_name = params['job_name'] || params[:job_name]
31
36
  config = Resque.schedule[@job_name]
@@ -38,6 +43,7 @@ module ResqueWeb
38
43
  end
39
44
  end
40
45
 
46
+ # POST /schedule/requeue_with_params
41
47
  def requeue_with_params
42
48
  job_name = params['job_name'] || params[:job_name]
43
49
  config = Resque.schedule[job_name]
@@ -1,7 +1,16 @@
1
1
  module ResqueWeb
2
2
  module Plugins
3
3
  module ResqueScheduler
4
+ # Helper methods for the delayed jobs UI
4
5
  module DelayedHelper
6
+ # Outputs the time in a human readable way.
7
+ #
8
+ # @example
9
+ # format_time(Time.at(timestamp))
10
+ #
11
+ # @param t [Time]
12
+ # @return [String] A string in this format: 2015-04-12 12:27:05 +0100
13
+ #
5
14
  def format_time(t)
6
15
  t.strftime('%Y-%m-%d %H:%M:%S %z')
7
16
  end
@@ -1,16 +1,31 @@
1
1
  module ResqueWeb
2
2
  module Plugins
3
3
  module ResqueScheduler
4
+ # Helper methods for the schedule UI
4
5
  module SchedulesHelper
6
+ # Tells us whether this job is scheduled for e.g. the production env.
7
+ # Jobs for other environments may be in Redis but should be ignored.
8
+ #
9
+ # @param [String] name
10
+ # @return [true, false]
5
11
  def scheduled_in_this_env?(name)
6
12
  return true if Resque.schedule[name]['rails_env'].nil?
7
13
  rails_env(name).split(/[\s,]+/).include?(Resque::Scheduler.env)
8
14
  end
9
15
 
16
+ # Returns the Rails env for the Resque schedule
17
+ #
18
+ # @param [String] name
19
+ # @return [String]
10
20
  def rails_env(name)
11
21
  Resque.schedule[name]['rails_env']
12
22
  end
13
23
 
24
+ # Outputs a human readable string showing the schedule for a job when it
25
+ # it configured for every X interval.
26
+ #
27
+ # @param [Array] every
28
+ # @return [String]
14
29
  def schedule_interval_every(every)
15
30
  every = [*every]
16
31
  s = 'every: ' << every.first
@@ -24,6 +39,11 @@ module ResqueWeb
24
39
  s << meta.join(', ') << ')'
25
40
  end
26
41
 
42
+ # Outputs a human readable string for the UI, showing when the job is
43
+ # scheduled.
44
+ #
45
+ # @param [Hash] config Config hash for one job
46
+ # @return [String]
27
47
  def schedule_interval(config)
28
48
  if config['every']
29
49
  schedule_interval_every(config['every'])
@@ -34,6 +54,10 @@ module ResqueWeb
34
54
  end
35
55
  end
36
56
 
57
+ # Retrieves the class name of the job from the job config and returns it
58
+ #
59
+ # @param [Hash] config
60
+ # @return [String]
37
61
  def schedule_class(config)
38
62
  if config['class'].nil? && !config['custom_job_class'].nil?
39
63
  config['custom_job_class']
@@ -42,9 +66,13 @@ module ResqueWeb
42
66
  end
43
67
  end
44
68
 
69
+ # Returns the name of the queue that a given class uses.
70
+ #
71
+ # @param [String] class_name
72
+ # @return [String]
45
73
  def queue_from_class_name(class_name)
46
74
  Resque.queue_from_class(
47
- Resque::Scheduler::Util.constantize(class_name)
75
+ Resque::Scheduler::Util.constantize(class_name)
48
76
  )
49
77
  end
50
78
  end
@@ -4,14 +4,19 @@ module ResqueWeb
4
4
  # This class exists to find jobs which match a search term. They may be
5
5
  # being processed, in the queue, or delayed.
6
6
  class JobFinder
7
-
7
+ # The search term that the user entered.
8
8
  attr_accessor :search_term
9
9
 
10
+ # @param [String] search_term
10
11
  def initialize(search_term = nil)
11
12
  @search_term = search_term || ''
12
13
  @search_term.downcase!
13
14
  end
14
15
 
16
+ # Finds all jobs that match the search term supplied when the class was
17
+ # initialized.
18
+ #
19
+ # @return [Array]
15
20
  def find_jobs
16
21
  return [] if search_term.empty?
17
22
  results = []
@@ -20,13 +25,15 @@ module ResqueWeb
20
25
  results + queued_jobs_where_class_name_matches_search_term
21
26
  end
22
27
 
28
+ protected
29
+
23
30
  def working_jobs_where_class_name_contains_search_term
24
31
  WorkingJobFinder.new(search_term).find_jobs
25
32
  end
26
33
 
27
34
  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)
35
+ delayed_job_timestamps.inject([]) do |jobs, timestamp|
36
+ jobs + delayed_jobs_for_timestamp_that_match_search_term(timestamp)
30
37
  end
31
38
  end
32
39
 
@@ -67,15 +74,14 @@ module ResqueWeb
67
74
  end
68
75
 
69
76
  def queued_jobs_from_queue(queue)
70
- bits = Resque.peek(queue, 0, Resque.size(queue))
71
- if bits.is_a? Array
72
- bits
77
+ jobs = Resque.peek(queue, 0, Resque.size(queue))
78
+ if jobs.is_a? Array
79
+ jobs
73
80
  else
74
- [bits]
81
+ [jobs]
75
82
  end
76
83
  end
77
-
78
84
  end
79
85
  end
80
86
  end
81
- end
87
+ end
@@ -4,15 +4,32 @@ module ResqueWeb
4
4
  class JobFinder
5
5
  # This class finds working jobs that Resque is currently processing
6
6
  class WorkingJobFinder
7
-
7
+ # The terms that the user entered.
8
8
  attr_accessor :search_term
9
9
 
10
+ # The search term will be used to match against the class name of any
11
+ # jobs that are currently being processed by any of the workers.
12
+ #
13
+ # @param search_term [String]
10
14
  def initialize(search_term)
11
15
  @search_term = search_term
12
16
  end
13
17
 
18
+ # Finds all jobs that match the search term provided when the class
19
+ # was instantiated.
20
+ #
21
+ # [
22
+ # {
23
+ # 'class' => 'SomeClass',
24
+ # 'queue' => 'some_queue',
25
+ # 'where_at' => 'working'
26
+ # }
27
+ # ]
28
+ #
29
+ # @return [Array] Returns an array of hashes.
30
+ #
14
31
  def find_jobs
15
- workers_with_jobs_that_match_search_term.collect do |w|
32
+ workers_with_jobs_that_match_search_term.map do |w|
16
33
  w.job['payload'].merge(
17
34
  'queue' => w.job['queue'],
18
35
  'where_at' => 'working'
@@ -20,6 +37,8 @@ module ResqueWeb
20
37
  end
21
38
  end
22
39
 
40
+ protected
41
+
23
42
  def workers_with_jobs_that_match_search_term
24
43
  all_working_jobs.select do |w|
25
44
  w.job &&
@@ -28,8 +47,6 @@ module ResqueWeb
28
47
  end
29
48
  end
30
49
 
31
- protected
32
-
33
50
  def all_working_jobs
34
51
  [*Resque.working]
35
52
  end
@@ -37,4 +54,4 @@ module ResqueWeb
37
54
  end
38
55
  end
39
56
  end
40
- end
57
+ end
@@ -23,7 +23,7 @@
23
23
  <th>All schedules</th>
24
24
  </tr>
25
25
  <% @timestamps.each do |timestamp| %>
26
- <tr>
26
+ <tr class="delayed-job">
27
27
  <td>
28
28
  <form action="<%= queue_now_path %>" method="post">
29
29
  <input type="hidden" name="timestamp" value="<%= timestamp.to_i %>">
@@ -1,4 +1,4 @@
1
- require "resque/scheduler/web/version"
1
+ require 'resque/scheduler/web/version'
2
2
 
3
3
  require 'resque_web'
4
4
  require 'resque/scheduler'
@@ -1,7 +1,7 @@
1
1
  module Resque
2
2
  module Scheduler
3
3
  module Web
4
- VERSION = "0.0.1"
4
+ VERSION = '0.0.2'
5
5
  end
6
6
  end
7
7
  end
@@ -3,16 +3,12 @@ require 'resque_web'
3
3
  module ResqueWeb
4
4
  module Plugins
5
5
  module ResqueScheduler
6
+ # Main engine class for the Resque Scheduler Web plugin.
6
7
  class Engine < ::Rails::Engine
7
8
  isolate_namespace ResqueWeb::Plugins::ResqueScheduler
8
-
9
- # paths['app'] << 'app'
10
- # paths['app/helpers'] << 'app/helpers'
11
- # paths['app/views'] << 'app/views'
12
- # paths['app/controllers'] << 'app/controllers'
13
- # paths['app/models'] << 'app/models'
14
9
  end
15
10
 
11
+ # Draws the routes for the engine.
16
12
  Engine.routes do
17
13
  get 'schedule', to: 'schedules#index', as: 'schedules'
18
14
  post 'schedule/requeue', to: 'schedules#requeue', as: 'requeue'
@@ -32,10 +28,18 @@ module ResqueWeb
32
28
  post '/delayed/clear', to: 'delayed#clear', as: 'clear'
33
29
  end
34
30
 
31
+ # provides the path where the engine will live. This is appended after
32
+ # the main resque-web path.
33
+ #
34
+ # @return [String]
35
35
  def self.engine_path
36
36
  '/scheduler'
37
37
  end
38
38
 
39
+ # Tells Resque web what extra tabs to ass to the main navigation at the
40
+ # top of the resque-web interface.
41
+ #
42
+ # @return [Array]
39
43
  def self.tabs
40
44
  [
41
45
  {