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.
- checksums.yaml +4 -4
- data/.gitignore +3 -3
- data/.rubocop.yml +1 -0
- data/.travis.yml +11 -0
- data/README.md +8 -2
- data/Rakefile +10 -1
- data/app/assets/javascripts/resque_web/plugins/resque_scheduler/application.js +0 -0
- data/app/assets/stylesheets/resque_web/plugins/resque_scheduler/application.css +3 -0
- data/app/controllers/resque_web/plugins/resque_scheduler/delayed_controller.rb +9 -1
- data/app/controllers/resque_web/plugins/resque_scheduler/schedules_controller.rb +7 -1
- data/app/helpers/resque_web/plugins/resque_scheduler/delayed_helper.rb +9 -0
- data/app/helpers/resque_web/plugins/resque_scheduler/schedules_helper.rb +29 -1
- data/app/models/resque_web/plugins/resque_scheduler/job_finder.rb +15 -9
- data/app/models/resque_web/plugins/resque_scheduler/job_finder/working_job_finder.rb +22 -5
- data/app/views/resque_web/plugins/resque_scheduler/delayed/index.erb +1 -1
- data/lib/resque/scheduler/web.rb +1 -1
- data/lib/resque/scheduler/web/version.rb +1 -1
- data/lib/resque_web/plugins/resque_scheduler/engine.rb +10 -6
- data/resque-scheduler-web.gemspec +10 -5
- data/spec/controllers/delayed_controller_spec.rb +10 -18
- data/spec/controllers/schedules_controller_spec.rb +28 -21
- data/spec/dummy/app/controllers/application_controller.rb +1 -0
- data/spec/dummy/config/application.rb +1 -0
- data/spec/dummy/log/test.log +5666 -0
- data/spec/features/navigation_spec.rb +1 -2
- data/spec/features/schedules/requeuing_a_job_with_parameters_spec.rb +8 -4
- data/spec/features/schedules/scheduled_jobs_page_spec.rb +8 -2
- data/spec/models/job_finder/working_job_finder_spec.rb +9 -7
- data/spec/models/job_finder_spec.rb +16 -13
- data/spec/rails_helper.rb +12 -9
- data/spec/routing/delayed_routing_spec.rb +5 -3
- data/spec/spec_helper.rb +6 -7
- data/spec/support/redis_instance.rb +13 -11
- data/spec/support/test_jobs.rb +9 -4
- metadata +68 -24
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 117651b5c62bac5f16c145b3f4aa0f6f38f3d9bc
|
4
|
+
data.tar.gz: 31af2fd0dc677d3014f097436dc1e7e2c06b577f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7205b8b5e211acac1efc24d102e34fe6cb2f7c0ff5f1a187b608dedb22c7a071577e629b4bf13e8c380e00ec184e4a833455929558d6fb8b240ded5552ec1cec
|
7
|
+
data.tar.gz: f70ea78760c27134564163b973f2a900c6ae797f8357526f5bf0bb1abfea5c33fb2a147cf8afa04f6497ce068d7898afa16edabbea8779517d0124fdde72ea14
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require: rubocop-rspec
|
data/.travis.yml
ADDED
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
|
32
|
-
|
38
|
+
bundle exec rake
|
33
39
|
|
34
40
|
## Contributing
|
35
41
|
|
data/Rakefile
CHANGED
File without changes
|
@@ -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
|
-
|
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 |
|
29
|
-
|
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
|
-
|
71
|
-
if
|
72
|
-
|
77
|
+
jobs = Resque.peek(queue, 0, Resque.size(queue))
|
78
|
+
if jobs.is_a? Array
|
79
|
+
jobs
|
73
80
|
else
|
74
|
-
[
|
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.
|
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
|
data/lib/resque/scheduler/web.rb
CHANGED
@@ -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
|
{
|