sidekiq-enqueuer 1.0.6 → 2.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/CHANGELOG.md +27 -0
- data/README.md +45 -1
- data/Rakefile +5 -5
- data/lib/sidekiq-enqueuer.rb +1 -1
- data/lib/sidekiq/enqueuer.rb +23 -72
- data/lib/sidekiq/enqueuer/configuration.rb +51 -0
- data/lib/sidekiq/enqueuer/version.rb +1 -1
- data/lib/sidekiq/enqueuer/views/index.erb +23 -21
- data/lib/sidekiq/enqueuer/views/new.erb +39 -56
- data/lib/sidekiq/enqueuer/web_extension/helper.rb +35 -0
- data/lib/sidekiq/enqueuer/web_extension/loader.rb +36 -0
- data/lib/sidekiq/enqueuer/web_extension/params_parser.rb +48 -0
- data/lib/sidekiq/enqueuer/worker/instance.rb +50 -0
- data/lib/sidekiq/enqueuer/worker/param.rb +20 -0
- data/lib/sidekiq/enqueuer/worker/trigger.rb +51 -0
- data/sidekiq-enqueuer.gemspec +12 -12
- metadata +12 -6
- data/Changes.md +0 -18
- data/lib/sidekiq/enqueuer/web_extension.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1585a3c676060297b1cc89c7b1c554fe8b1b05d1
|
4
|
+
data.tar.gz: 004294f3a7df7865e4b6b3cfa7f2aa9f1839c808
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f956108676be7658c630fc4dd19115e9dd23ab4b434aaef81369f5680d195ca9dba7e411be5f33887fd396ecc3f4bff7efa73c89880f330a3ed9b348253a0042
|
7
|
+
data.tar.gz: 514423672fc749f515637eacd92251be9ec1169a94070adf3af6e6a0e90ab1e73915af23286645df4084c3c6a9a2883c815f74caaf819e1e3974b0c253d7ee89
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Sidekiq Enqueuer Changes
|
2
|
+
|
3
|
+
2.0.0.beta
|
4
|
+
-----------
|
5
|
+
|
6
|
+
- Added configutation option: Provides a list of Jobs to display
|
7
|
+
- Dropped support for manual 'unlock'
|
8
|
+
- Sidekiq enqueing now uses `Sidekiq::Client.enqueue_to / enqueue_to_in` to a custom queue.
|
9
|
+
- Refactor on classes and modules to bring Atomicity
|
10
|
+
|
11
|
+
|
12
|
+
1.0.6
|
13
|
+
-----------
|
14
|
+
|
15
|
+
- Jobs are sorted by name by default
|
16
|
+
|
17
|
+
|
18
|
+
1.0.4
|
19
|
+
-----------
|
20
|
+
|
21
|
+
- Support for jobs without arguments
|
22
|
+
|
23
|
+
|
24
|
+
1.0.3
|
25
|
+
-----------
|
26
|
+
|
27
|
+
- Support unlock! for sidekiq-middleware
|
data/README.md
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# Sidekiq::Enqueuer
|
2
|
+
[![Build Status](https://travis-ci.org/vgarro/sidekiq-enqueuer.svg?branch=vg%2Fconfig-option-and-refactor)](https://travis-ci.org/vgarro/sidekiq-enqueuer)
|
2
3
|
|
3
4
|
A Sidekiq Web extension to enqueue/schedule job in Web UI. Support both Sidekiq::Worker and ActiveJob.
|
4
5
|
|
@@ -21,6 +22,49 @@ Edit config/initializers/sidekiq.rb, add following line
|
|
21
22
|
require 'sidekiq/enqueuer'
|
22
23
|
```
|
23
24
|
|
25
|
+
Optionally, provide a list of Jobs to display on the new tab, on a new initializer file.
|
26
|
+
Worry not, when no configuration is provided, All jobs will be displayed
|
27
|
+
|
28
|
+
```
|
29
|
+
# config/initializers/sidekiq_enqueuer_config.rb
|
30
|
+
require 'sidekiq/enqueuer'
|
31
|
+
|
32
|
+
Sidekiq::Enqueuer.configure do |config|
|
33
|
+
config.jobs = [MyAwesomeJob1, MyModule::MyAwesomeJob2]
|
34
|
+
end
|
35
|
+
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
## Notes:
|
40
|
+
|
41
|
+
### Queuing & ActiveJob support
|
42
|
+
Use default sidekiq queue adapter for Jobs including Sidekiq::Worker or Jobs inheriting from ActiveJob::base
|
43
|
+
|
44
|
+
```
|
45
|
+
ActiveJob::Base.queue_adapter = :sidekiq
|
46
|
+
```
|
47
|
+
https://github.com/mperham/sidekiq/wiki/Active-Job#active-job-setup
|
48
|
+
|
49
|
+
|
50
|
+
### Jobs action param mapping.
|
51
|
+
This gem dynamically infers the params required in the `perform` or `perform_in` action in your Job / Worker.
|
52
|
+
It is important those actions (either of them) won't hide the actual params into a single *args one.
|
53
|
+
In that case it will be impossible to infer the params for your method.
|
54
|
+
|
55
|
+
Want to verify this last line? Run this in a rails console:
|
56
|
+
```
|
57
|
+
MyJob.instance_method(:perform).parameters # change :perform for your implemented method
|
58
|
+
>> [[:req, :param1], [:opt, :param2], [:opt, :param3]] # Good output
|
59
|
+
|
60
|
+
=> [[:rest, :args], [:block, :block]] # Bad output. Params are being wrapped into a super class.
|
61
|
+
```
|
62
|
+
|
63
|
+
### Enqueuing Jobs:
|
64
|
+
|
65
|
+
For Sidekiq, enqueing is being done using `Sidekiq::Client.enqueue_to` / `enqueue_to_in`, providing Job, and queue extracted from the Job sidekiq_options hash, defaults to 'default' queue when not present.
|
66
|
+
|
67
|
+
For ActiveJob, enqueing is being done calling the very own `perform_later` instance method. Please advise your Job should respond to `perform_later` to correctly work.
|
24
68
|
|
25
69
|
## Usage
|
26
70
|
|
@@ -30,7 +74,7 @@ require 'sidekiq/enqueuer'
|
|
30
74
|
|
31
75
|
![list](https://cloud.githubusercontent.com/assets/830633/14494297/c9b01b10-01bc-11e6-8ef5-a4d29ff45fb3.png)
|
32
76
|
|
33
|
-
* Fill the form, click Enqueue or Schedule.
|
77
|
+
* Fill the form, click Enqueue or Schedule.
|
34
78
|
![form](https://cloud.githubusercontent.com/assets/830633/14494314/ddd9f8ae-01bc-11e6-86ce-0641a9c4d3e4.png)
|
35
79
|
|
36
80
|
* That is it!
|
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
3
|
|
4
4
|
task :default => :test
|
5
5
|
|
6
6
|
Rake::TestTask.new do |t|
|
7
|
-
t.libs <<
|
8
|
-
t.libs <<
|
9
|
-
t.test_files = FileList[
|
7
|
+
t.libs << 'lib'
|
8
|
+
t.libs << 'test'
|
9
|
+
t.test_files = FileList['test/**/*_test.rb']
|
10
10
|
t.verbose = true
|
11
11
|
end
|
data/lib/sidekiq-enqueuer.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require 'sidekiq/enqueuer'
|
1
|
+
require 'sidekiq/enqueuer'
|
data/lib/sidekiq/enqueuer.rb
CHANGED
@@ -1,88 +1,39 @@
|
|
1
1
|
require 'sidekiq/web'
|
2
|
-
require
|
3
|
-
require 'sidekiq/enqueuer/
|
2
|
+
require 'sidekiq/enqueuer/version'
|
3
|
+
require 'sidekiq/enqueuer/configuration'
|
4
|
+
require 'sidekiq/enqueuer/worker/instance'
|
5
|
+
require 'sidekiq/enqueuer/worker/param'
|
6
|
+
require 'sidekiq/enqueuer/worker/trigger'
|
7
|
+
require 'sidekiq/enqueuer/web_extension/loader'
|
8
|
+
require 'sidekiq/enqueuer/web_extension/helper'
|
9
|
+
require 'sidekiq/enqueuer/web_extension/params_parser'
|
4
10
|
require 'sidekiq/enqueuer/railtie' if defined? ::Rails::Railtie
|
5
11
|
|
6
12
|
module Sidekiq
|
7
13
|
module Enqueuer
|
8
|
-
|
9
|
-
|
10
|
-
::Rails.application.eager_load!
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.get_job_modules
|
15
|
-
ObjectSpace.each_object(Module)
|
16
|
-
.select { |klass| has_worker_module?(klass) }
|
17
|
-
.delete_if { |klass| klass.to_s =~ /^Sidekiq::Extensions/ }
|
18
|
-
.delete_if { |klass| klass.to_s =~ /^ActiveJob::QueueAdapters/ }
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.get_job_classes
|
22
|
-
ObjectSpace.each_object(Class)
|
23
|
-
.select { |klass| is_job_class?(klass) }
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.get_jobs
|
27
|
-
return @jobs if @jobs
|
28
|
-
|
29
|
-
rails_eager_load
|
30
|
-
jobs = get_job_modules + get_job_classes
|
31
|
-
jobs = jobs.map(&:to_s).uniq.map(&:constantize)
|
32
|
-
@jobs = jobs.sort_by(&:name)
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.is_job_class?(klass)
|
36
|
-
return false if !defined?(::ActiveJob)
|
14
|
+
class << self
|
15
|
+
attr_accessor :configuration
|
37
16
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
def self.has_worker_module?(klass)
|
42
|
-
klass.included_modules.include? ::Sidekiq::Worker
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.perform_async(klass, values)
|
46
|
-
parsed_values = values_parser(values)
|
47
|
-
if is_job_class?(klass)
|
48
|
-
klass.perform_later(*parsed_values)
|
49
|
-
elsif has_worker_module?(klass)
|
50
|
-
klass.perform_async(*parsed_values)
|
17
|
+
def configuration
|
18
|
+
@configuration ||= Configuration.new
|
51
19
|
end
|
52
|
-
end
|
53
20
|
|
54
|
-
|
55
|
-
|
56
|
-
seconds = seconds_str.to_i.seconds
|
57
|
-
if is_job_class?(klass)
|
58
|
-
klass.set(wait: seconds).perform_later(*parsed_values)
|
59
|
-
elsif has_worker_module?(klass)
|
60
|
-
klass.perform_in(seconds, *parsed_values)
|
21
|
+
def configure
|
22
|
+
yield(configuration)
|
61
23
|
end
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.unlock!(klass, values)
|
65
|
-
parsed_values = values_parser(values)
|
66
|
-
klass.unlock!(*parsed_values)
|
67
|
-
end
|
68
24
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
if value =~ /^{/
|
74
|
-
parsed_values << YAML.load(value) rescue errors << value
|
75
|
-
else
|
76
|
-
parsed_values << value
|
25
|
+
def all_jobs
|
26
|
+
included_jobs = defined?(@all_jobs) ? @all_jobs : configuration.all_jobs
|
27
|
+
included_jobs.each_with_object([]) do |job_klass, acc|
|
28
|
+
acc << Worker::Instance.new(job_klass, configuration.enqueue_using_async)
|
77
29
|
end
|
78
30
|
end
|
79
|
-
raise errors if errors.size > 0
|
80
|
-
parsed_values
|
81
31
|
end
|
82
|
-
|
83
32
|
end
|
84
33
|
end
|
85
34
|
|
86
|
-
Sidekiq::Web
|
87
|
-
Sidekiq::Web.
|
88
|
-
Sidekiq::Web.
|
35
|
+
if defined?(Sidekiq::Web)
|
36
|
+
Sidekiq::Web.register Sidekiq::Enqueuer::WebExtension::Loader
|
37
|
+
Sidekiq::Web.tabs['Enqueuer'] = 'enqueuer'
|
38
|
+
Sidekiq::Web.settings.locales << File.join(File.dirname(__FILE__), 'enqueuer/locales')
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :jobs, :enqueue_using_async
|
5
|
+
|
6
|
+
IGNORED_CLASSES = %w(Sidekiq::Extensions
|
7
|
+
Sidekiq::Extensions::DelayedModel
|
8
|
+
Sidekiq::Extensions::DelayedMailer
|
9
|
+
Sidekiq::Extensions::DelayedClass
|
10
|
+
ActiveJob::QueueAdapters).freeze
|
11
|
+
|
12
|
+
def initialize(enqueue_using_async = nil)
|
13
|
+
@enqueue_using_async = true if enqueue_using_async.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def all_jobs
|
17
|
+
@jobs = defined?(@jobs) ? sort(@jobs) : sort(application_jobs)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def sort(all_jobs)
|
23
|
+
all_jobs.sort_by(&:name)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Loads all jobs within the application after an eager_load
|
27
|
+
# Filters Sidekiq system Jobs
|
28
|
+
def application_jobs
|
29
|
+
rails_eager_load
|
30
|
+
all_jobs = []
|
31
|
+
all_jobs << sidekiq_jobs
|
32
|
+
all_jobs << active_jobs
|
33
|
+
all_jobs = all_jobs.flatten
|
34
|
+
all_jobs.delete_if { |klass| IGNORED_CLASSES.include?(klass.to_s) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def sidekiq_jobs
|
38
|
+
ObjectSpace.each_object(Class).select { |k| k.included_modules.include?(::Sidekiq::Worker) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def active_jobs
|
42
|
+
ObjectSpace.each_object(Class).select { |k| k.superclass == ::ActiveJob::Base }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Load all classes from the included application before selecting Jobs from it
|
46
|
+
def rails_eager_load
|
47
|
+
::Rails.application.eager_load! if defined?(::Rails) && !::Rails.env.production?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,24 +1,26 @@
|
|
1
1
|
<h3>Enqueuer</h3>
|
2
2
|
|
3
3
|
<table class="table table-hover table-bordered table-striped table-white">
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th>Name</th>
|
7
|
+
<th>Params</th>
|
8
|
+
<th>Actions</th>
|
9
|
+
</tr>
|
10
|
+
</thead>
|
11
|
+
<tbody>
|
12
|
+
<% @jobs.each do |job| %>
|
13
|
+
<tr>
|
14
|
+
<td width="40%"><%= job.name %></td>
|
15
|
+
<td width="40%"><%= job.params.map(&:name).join(', ') %></td>
|
16
|
+
<td width="20%">
|
17
|
+
<button class="btn btn-danger btn-xs">
|
18
|
+
<a href="<%= root_path %>enqueuer/<%= job.name %>" style="color: white;">
|
19
|
+
Enqueue Form
|
20
|
+
</a>
|
21
|
+
</button>
|
22
|
+
</td>
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
@@ -1,63 +1,46 @@
|
|
1
1
|
<h3>Enqueuer</h3>
|
2
2
|
|
3
3
|
<div class="well">
|
4
|
-
|
5
|
-
|
4
|
+
<p>Support string value and hash value. Value will be stripped.</p>
|
5
|
+
<p>Start with { will be parsed by YAML as hash, eg: {k1: v1, k2: v2} to {'k1'=> 'v1', 'k2'=> 'v2'}. </p>
|
6
6
|
</div>
|
7
7
|
|
8
8
|
<form method="post" action="<%= root_path %>enqueuer">
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
</div>
|
47
|
-
<% end %>
|
48
|
-
|
49
|
-
<div class="form-group">
|
50
|
-
<input type="submit" class="btn btn-danger" name="submit" value="Enqueue" />
|
51
|
-
</div>
|
52
|
-
|
53
|
-
<div class="form-group">
|
54
|
-
<hr />
|
55
|
-
</div>
|
56
|
-
|
57
|
-
<div class="form-group">
|
58
|
-
<label for="enqueue_in">Enqueue in</label>
|
59
|
-
<input class="form-control" name="enqueue_in" placeholder="x seconds" />
|
60
|
-
</div>
|
61
|
-
|
62
|
-
<input type="submit" class="btn btn-danger" name="submit" value="Schedule" />
|
9
|
+
<%= csrf_tag if respond_to?(:csrf_tag) %>
|
10
|
+
|
11
|
+
<div class="panel panel-default">
|
12
|
+
<div class="panel-heading">
|
13
|
+
<h3 class="panel-title">Perform</h3>
|
14
|
+
</div>
|
15
|
+
<div class="panel-body">
|
16
|
+
<div class="form-group">
|
17
|
+
<label for="job_class_name">Job Class/Module</label>
|
18
|
+
<input class="form-control" name="job_class_name" value="<%= @job.name %>" readonly=readonly />
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<% @job.params.each do |param| %>
|
22
|
+
<div class="form-group">
|
23
|
+
<label for="perform[<%= param %>]"><%= param.name %>
|
24
|
+
<span style="color: red; font-size: small;"> *<%= param.label %></span>
|
25
|
+
</label>
|
26
|
+
<input class="form-control" name="perform[<%= param.name %>]" />
|
27
|
+
</div>
|
28
|
+
<% end %>
|
29
|
+
</div>
|
30
|
+
</div>
|
31
|
+
|
32
|
+
<div class="form-group">
|
33
|
+
<input type="submit" class="btn btn-danger" name="submit" value="Enqueue" />
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<div class="form-group">
|
37
|
+
<hr />
|
38
|
+
</div>
|
39
|
+
|
40
|
+
<div class="form-group">
|
41
|
+
<label for="enqueue_in">Enqueue in</label>
|
42
|
+
<input class="form-control" name="enqueue_in" placeholder="x seconds" />
|
43
|
+
</div>
|
44
|
+
|
45
|
+
<input type="submit" class="btn btn-danger" name="submit" value="Schedule" />
|
63
46
|
</form>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module WebExtension
|
4
|
+
module Helper
|
5
|
+
def get_params_by_action(name)
|
6
|
+
return [] if params[name].nil?
|
7
|
+
ParamsParser.new(params[name]).process
|
8
|
+
end
|
9
|
+
|
10
|
+
def find_job_by_class_name(job_class_name)
|
11
|
+
Sidekiq::Enqueuer.all_jobs.find do |job_klass|
|
12
|
+
job_klass.job == job_class_name || job_klass.job.to_s == job_class_name || job_klass.name == job_class_name
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# TODO: Figure out the need of unlock!
|
17
|
+
# def does_job_have_unlock_method(klass_or_module)
|
18
|
+
# klass_or_module.respond_to?(:unlock!)
|
19
|
+
# false
|
20
|
+
# end
|
21
|
+
|
22
|
+
# TODO: Figure out the need of unlock!
|
23
|
+
# def get_job_unlock_params(klass_or_module)
|
24
|
+
# klass_or_module.method(:unlock!).parameters.map{ |e| e[1]}
|
25
|
+
# end
|
26
|
+
|
27
|
+
# TODO: Figure out the need of unlock!
|
28
|
+
# def self.unlock!(klass, values)
|
29
|
+
# parsed_values = values_parser(values)
|
30
|
+
# klass.unlock!(*parsed_values)
|
31
|
+
# end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module WebExtension
|
4
|
+
module Loader
|
5
|
+
def self.registered(app)
|
6
|
+
view_path = File.join(File.expand_path('../..', __FILE__), 'views')
|
7
|
+
app.helpers WebExtension::Helper
|
8
|
+
|
9
|
+
app.get '/enqueuer' do
|
10
|
+
@jobs = Sidekiq::Enqueuer.all_jobs
|
11
|
+
render(:erb, File.read(File.join(view_path, 'index.erb')))
|
12
|
+
end
|
13
|
+
|
14
|
+
app.get '/enqueuer/:job_class_name' do
|
15
|
+
@job = find_job_by_class_name(params[:job_class_name])
|
16
|
+
render(:erb, File.read(File.join(view_path, 'new.erb')))
|
17
|
+
end
|
18
|
+
|
19
|
+
app.post '/enqueuer' do
|
20
|
+
job = find_job_by_class_name(params[:job_class_name])
|
21
|
+
requested_params = get_params_by_action('perform')
|
22
|
+
# TODO: Figure out the need of unlock!
|
23
|
+
# if params['unlock-enable'] && params['unlock-enable'] != ''
|
24
|
+
# Sidekiq::Enqueuer.unlock!(klass, get_params_by_action('unlock'))
|
25
|
+
# end
|
26
|
+
if job
|
27
|
+
job.trigger(requested_params) if params['submit'] == 'Enqueue'
|
28
|
+
job.trigger_in(params['enqueue_in'], requested_params) if params['submit'] == 'Schedule'
|
29
|
+
end
|
30
|
+
redirect "#{root_path}enqueuer"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module WebExtension
|
4
|
+
class ParamsParser
|
5
|
+
attr_reader :raw_params
|
6
|
+
|
7
|
+
def initialize(params)
|
8
|
+
@raw_params = params
|
9
|
+
end
|
10
|
+
|
11
|
+
def process
|
12
|
+
all_params = filter_empty(raw_params)
|
13
|
+
hash_params = yaml_to_params(all_params.values)
|
14
|
+
all_params = hash_params.merge!(all_params) if hash_params
|
15
|
+
simple_params = filter_complex(all_params)
|
16
|
+
simple_params.values.compact.flatten
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def yaml_to_params(values)
|
22
|
+
unique_params = {}
|
23
|
+
values.each do |str_param|
|
24
|
+
param_hash = expected_hash?(str_param) ? convert_to_ruby(str_param) : {}
|
25
|
+
unique_params.merge!(param_hash)
|
26
|
+
end
|
27
|
+
unique_params
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter_empty(given_params)
|
31
|
+
given_params.delete_if { |_, v| v.to_s.empty? }
|
32
|
+
end
|
33
|
+
|
34
|
+
def filter_complex(given_params)
|
35
|
+
given_params.delete_if { |_, v| expected_hash?(v.to_s) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_to_ruby(value)
|
39
|
+
YAML.parse(value.to_s.strip).to_ruby
|
40
|
+
end
|
41
|
+
|
42
|
+
def expected_hash?(value)
|
43
|
+
value.to_s.start_with?('{') && value.to_s.end_with?('}')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module Worker
|
4
|
+
class Instance
|
5
|
+
attr_reader :job, :instance_method, :params, :enqueue_using_async
|
6
|
+
|
7
|
+
def initialize(job, enqueue_using_async)
|
8
|
+
@job = job
|
9
|
+
@enqueue_using_async = enqueue_using_async
|
10
|
+
@instance_method = deduce_instance_method
|
11
|
+
@params = deduce_params
|
12
|
+
end
|
13
|
+
|
14
|
+
def trigger(input_params)
|
15
|
+
trigger_job(input_params).enqueue
|
16
|
+
end
|
17
|
+
|
18
|
+
def trigger_in(seconds, input_params)
|
19
|
+
trigger_job(input_params).enqueue_in(seconds.to_s.to_i.seconds)
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
@job.name
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def trigger_job(input_params)
|
29
|
+
Trigger.new(job, input_params)
|
30
|
+
end
|
31
|
+
|
32
|
+
# TODO: what if two of this methods exist? which one to pick to figure out params?
|
33
|
+
def deduce_instance_method
|
34
|
+
[:perform, :perform_in, :perform_async, :perform_at].each do |evaluating_method|
|
35
|
+
return evaluating_method if job.instance_methods.include?(evaluating_method)
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def deduce_params
|
41
|
+
worker_params.empty? ? [] : worker_params.map { |e| Param.new(e[1], e[0]) }
|
42
|
+
end
|
43
|
+
|
44
|
+
def worker_params
|
45
|
+
job.instance_method(instance_method).parameters
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module Worker
|
4
|
+
class Param
|
5
|
+
attr_reader :name, :condition
|
6
|
+
|
7
|
+
VALID_OPTIONS = { req: 'required', opt: 'optional' }.freeze
|
8
|
+
|
9
|
+
def initialize(name, condition)
|
10
|
+
@name = name
|
11
|
+
@condition = VALID_OPTIONS[condition]
|
12
|
+
end
|
13
|
+
|
14
|
+
def label
|
15
|
+
condition
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Sidekiq
|
2
|
+
module Enqueuer
|
3
|
+
module Worker
|
4
|
+
class Trigger
|
5
|
+
class UnsupportedJobType < StandardError; end
|
6
|
+
|
7
|
+
attr_reader :job, :queue, :args_with_values
|
8
|
+
|
9
|
+
def initialize(job, input_param_hash)
|
10
|
+
@job = job
|
11
|
+
@queue = deduce_queue
|
12
|
+
@args_with_values = input_param_hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def enqueue
|
16
|
+
if sidekiq_job?
|
17
|
+
Sidekiq::Client.enqueue_to(queue, job, *args_with_values)
|
18
|
+
elsif active_job?
|
19
|
+
return job.perform_later(*args_with_values)
|
20
|
+
else
|
21
|
+
raise UnsupportedJobType
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def enqueue_in(time_in_seconds)
|
26
|
+
if sidekiq_job?
|
27
|
+
Sidekiq::Client.enqueue_to_in(queue, time_in_seconds, job, *args_with_values)
|
28
|
+
elsif active_job?
|
29
|
+
job.set(wait: time_in_seconds).perform_later(*args_with_values)
|
30
|
+
else
|
31
|
+
raise UnsupportedJobType
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def deduce_queue
|
38
|
+
job.respond_to?(:sidekiq_options) ? job.sidekiq_options['queue'].to_s : 'default'
|
39
|
+
end
|
40
|
+
|
41
|
+
def sidekiq_job?
|
42
|
+
job.included_modules.include? ::Sidekiq::Worker
|
43
|
+
end
|
44
|
+
|
45
|
+
def active_job?
|
46
|
+
job.superclass == ::ActiveJob::Base
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/sidekiq-enqueuer.gemspec
CHANGED
@@ -4,14 +4,14 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'sidekiq/enqueuer/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'sidekiq-enqueuer'
|
8
8
|
spec.version = Sidekiq::Enqueuer::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
9
|
+
spec.authors = ['richfisher']
|
10
|
+
spec.email = ['richfisher.pan@gmail.com']
|
11
11
|
|
12
12
|
spec.summary = %q{A Sidekiq Web extension to enqueue/schedule jobs with custom perform params in Web UI.}
|
13
13
|
spec.description = %q{A Sidekiq Web extension to enqueue/schedule jobs with custom perform params in Web UI. Support both Sidekiq::Worker and ActiveJob.}
|
14
|
-
spec.homepage =
|
14
|
+
spec.homepage = 'https://github.com/richfisher/sidekiq-enqueuer'
|
15
15
|
|
16
16
|
# Prevent pushing this gem to RubyGems.org by setting 'allowed_push_host', or
|
17
17
|
# delete this section to allow pushing this gem to any host.
|
@@ -22,14 +22,14 @@ Gem::Specification.new do |spec|
|
|
22
22
|
# end
|
23
23
|
|
24
24
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
25
|
-
spec.bindir =
|
25
|
+
spec.bindir = 'exe'
|
26
26
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
|
-
spec.require_paths = [
|
27
|
+
spec.require_paths = ['lib']
|
28
28
|
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
29
|
+
spec.add_development_dependency 'bundler'
|
30
|
+
spec.add_development_dependency 'rake'
|
31
|
+
spec.add_development_dependency 'rack-test'
|
32
|
+
spec.add_development_dependency 'sidekiq'
|
33
|
+
spec.add_development_dependency 'rails', '> 4.2'
|
34
|
+
spec.add_development_dependency 'sinatra'
|
35
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq-enqueuer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- richfisher
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -105,7 +105,7 @@ files:
|
|
105
105
|
- ".gitignore"
|
106
106
|
- ".ruby-version"
|
107
107
|
- ".travis.yml"
|
108
|
-
-
|
108
|
+
- CHANGELOG.md
|
109
109
|
- Gemfile
|
110
110
|
- README.md
|
111
111
|
- Rakefile
|
@@ -113,12 +113,18 @@ files:
|
|
113
113
|
- bin/setup
|
114
114
|
- lib/sidekiq-enqueuer.rb
|
115
115
|
- lib/sidekiq/enqueuer.rb
|
116
|
+
- lib/sidekiq/enqueuer/configuration.rb
|
116
117
|
- lib/sidekiq/enqueuer/locales/en.yml
|
117
118
|
- lib/sidekiq/enqueuer/railtie.rb
|
118
119
|
- lib/sidekiq/enqueuer/version.rb
|
119
120
|
- lib/sidekiq/enqueuer/views/index.erb
|
120
121
|
- lib/sidekiq/enqueuer/views/new.erb
|
121
|
-
- lib/sidekiq/enqueuer/web_extension.rb
|
122
|
+
- lib/sidekiq/enqueuer/web_extension/helper.rb
|
123
|
+
- lib/sidekiq/enqueuer/web_extension/loader.rb
|
124
|
+
- lib/sidekiq/enqueuer/web_extension/params_parser.rb
|
125
|
+
- lib/sidekiq/enqueuer/worker/instance.rb
|
126
|
+
- lib/sidekiq/enqueuer/worker/param.rb
|
127
|
+
- lib/sidekiq/enqueuer/worker/trigger.rb
|
122
128
|
- sidekiq-enqueuer.gemspec
|
123
129
|
homepage: https://github.com/richfisher/sidekiq-enqueuer
|
124
130
|
licenses: []
|
@@ -134,9 +140,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
140
|
version: '0'
|
135
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
142
|
requirements:
|
137
|
-
- - "
|
143
|
+
- - ">"
|
138
144
|
- !ruby/object:Gem::Version
|
139
|
-
version:
|
145
|
+
version: 1.3.1
|
140
146
|
requirements: []
|
141
147
|
rubyforge_project:
|
142
148
|
rubygems_version: 2.4.8
|
data/Changes.md
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
module Sidekiq::Enqueuer::WebExtension
|
2
|
-
def self.registered(app)
|
3
|
-
view_path = File.join(File.expand_path("..", __FILE__), "views")
|
4
|
-
|
5
|
-
app.helpers do
|
6
|
-
def get_job_perform_params(klass_or_module)
|
7
|
-
klass_or_module.instance_method(:perform).parameters.map{ |e| e[1]}
|
8
|
-
end
|
9
|
-
|
10
|
-
def does_job_have_unlock_method(klass_or_module)
|
11
|
-
klass_or_module.respond_to?(:unlock!)
|
12
|
-
end
|
13
|
-
|
14
|
-
def get_job_unlock_params(klass_or_module)
|
15
|
-
klass_or_module.method(:unlock!).parameters.map{ |e| e[1]}
|
16
|
-
end
|
17
|
-
|
18
|
-
def get_params_by_name(name)
|
19
|
-
params[name].nil? ? [] : params[name].values
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
app.get "/enqueuer" do
|
24
|
-
@jobs = Sidekiq::Enqueuer.get_jobs
|
25
|
-
|
26
|
-
render(:erb, File.read(File.join(view_path, "index.erb")))
|
27
|
-
end
|
28
|
-
|
29
|
-
app.get "/enqueuer/:job_class_name" do
|
30
|
-
@klass = params[:job_class_name].constantize
|
31
|
-
render(:erb, File.read(File.join(view_path, "new.erb")))
|
32
|
-
end
|
33
|
-
|
34
|
-
app.post "/enqueuer" do
|
35
|
-
klass = params[:job_class_name].constantize
|
36
|
-
|
37
|
-
if params['unlock-enable'] && params['unlock-enable'] != ''
|
38
|
-
Sidekiq::Enqueuer.unlock!(klass, get_params_by_name('unlock'))
|
39
|
-
end
|
40
|
-
|
41
|
-
if params['submit'] == 'Enqueue'
|
42
|
-
Sidekiq::Enqueuer.perform_async(klass, get_params_by_name('perform'))
|
43
|
-
end
|
44
|
-
|
45
|
-
if params['submit'] == 'Schedule'
|
46
|
-
Sidekiq::Enqueuer.perform_in(klass, params['enqueue_in'], get_params_by_name('perform'))
|
47
|
-
end
|
48
|
-
|
49
|
-
redirect "#{root_path}enqueuer"
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
53
|
-
end
|