sidekiq_adhoc_job 0.1.5 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c0f35c0912b36fde038556110a6a116b789aaaf62cab80bd43521e1c50eec4ec
4
- data.tar.gz: 18913f33c03e1a976bafeac7fa03f575f87c43f6a325c00d92f9b22370014667
3
+ metadata.gz: 756b8b12f8763a43f6fdcf9608c244e7c6858cb05c7b342414377fb4f37184d3
4
+ data.tar.gz: 8ebbe33d96929bd6a50a5cd11a10cbd969a2d19aee72ca39e64cbca1e0a8e98c
5
5
  SHA512:
6
- metadata.gz: 1790167e58fe6b6cfe2ec654e00801b31249e04041463505130f4d0857162dd4b55f2234e3ea2fb1cba1ad0d54e2601ca8d640eff7bb4e2aac94bd33f9cf0845
7
- data.tar.gz: a7e0161b04b1cfbe0a7b0b7e9038f8c0802952925b33ed05ec3f356160d0ba2c9dd967f16e04bc4d9cfad70c178c31cd8311a61c434e60fc689a7cc1fc1fc76b
6
+ metadata.gz: eaaa17c4ef1866a26d479d24b8c7c0d7d1c26987a77aec481bf5541df9c1e65910e275f9728ec9cbc1058f05982ea9e3514bd9447a22a19034f6273badaf3e21
7
+ data.tar.gz: b1287b3d6205a94ef56cd4d4d7daf98dc00662b0fc40c22555678836131082cee76414d493760e52a3e395bc52130785988f38a215af00e19e0c2e7e8d74cc5c
@@ -3,6 +3,7 @@ require 'sidekiq/web'
3
3
 
4
4
  require 'sidekiq_adhoc_job/utils/string'
5
5
  require 'sidekiq_adhoc_job/utils/class_inspector'
6
+ require 'sidekiq_adhoc_job/strategy'
6
7
  require 'sidekiq_adhoc_job/worker_classes_loader'
7
8
  require 'sidekiq_adhoc_job/web/job_presenter'
8
9
  require 'sidekiq_adhoc_job/services/schedule_adhoc_job'
@@ -10,7 +11,13 @@ require 'sidekiq_adhoc_job/web'
10
11
 
11
12
  module SidekiqAdhocJob
12
13
 
13
- InvalidConfigurationError ||= Class.new(RuntimeError)
14
+ StringUtil ||= Utils::String
15
+
16
+ module Strategies
17
+ autoload :Default, 'sidekiq_adhoc_job/strategies/default'
18
+ autoload :ActiveJob, 'sidekiq_adhoc_job/strategies/active_job'
19
+ autoload :RailsApplicationJob, 'sidekiq_adhoc_job/strategies/rails_application_job'
20
+ end
14
21
 
15
22
  def self.configure
16
23
  @_config = Configuration.new
@@ -22,24 +29,39 @@ module SidekiqAdhocJob
22
29
  end
23
30
 
24
31
  def self.init
25
- raise InvalidConfigurationError, 'Must configure before init' unless @_config&.configured?
26
-
27
- SidekiqAdhocJob::WorkerClassesLoader.load(@_config.module_names)
32
+ SidekiqAdhocJob::WorkerClassesLoader.load(@_config.module_names, load_paths: @_config.load_paths, strategy: @_config.strategy)
28
33
 
29
34
  Sidekiq::Web.register(SidekiqAdhocJob::Web)
30
35
  Sidekiq::Web.tabs['adhoc_jobs'] = 'adhoc-jobs'
31
36
  Sidekiq::Web.locales << File.expand_path('sidekiq_adhoc_job/web/locales', __dir__)
32
37
  end
33
38
 
39
+ def self.strategies
40
+ @_strategies ||= []
41
+ end
42
+
34
43
  class Configuration
35
- attr_accessor :module_names
44
+ attr_accessor :load_paths, :module_names, :strategy_name
36
45
 
37
46
  def initialize
47
+ @load_paths = []
38
48
  @module_names = []
49
+ @strategy_name = :default
50
+ end
51
+
52
+ def module_names
53
+ Array(@module_names).map(&:to_s)
39
54
  end
40
55
 
41
- def configured?
42
- !@module_names.empty?
56
+ def strategy
57
+ @strategy ||= case strategy_name
58
+ when :default
59
+ SidekiqAdhocJob::Strategies::Default.new(module_names)
60
+ else
61
+ strategy_klass = SidekiqAdhocJob::Strategies.const_get(StringUtil.camelize(strategy_name.to_s).to_s)
62
+ raise InvalidConfigurationError, "Invalid strategy name" unless strategy_klass
63
+ strategy_klass.new(module_names)
64
+ end
43
65
  end
44
66
  end
45
67
 
@@ -16,7 +16,7 @@ module SidekiqAdhocJob
16
16
  end
17
17
 
18
18
  def call
19
- worker_klass.perform_async(*worker_params)
19
+ SidekiqAdhocJob.config.strategy.perform_async(worker_klass, *worker_params)
20
20
  end
21
21
 
22
22
  private
@@ -25,9 +25,11 @@ module SidekiqAdhocJob
25
25
  :allowed_params, :worker_params
26
26
 
27
27
  def parse_params
28
- @worker_params = allowed_params.map { |key| StringUtil.parse(request_params[key]) }
28
+ @worker_params = allowed_params
29
+ .reject { |key| request_params[key].empty? }
30
+ .map { |key| StringUtil.parse(request_params[key], symbolize: true) }
29
31
  if !!request_params[:rest_args] && !request_params[:rest_args].empty?
30
- @worker_params += request_params[:rest_args].split(',').map { |arg| StringUtil.parse(arg.strip) }
32
+ @worker_params << StringUtil.parse_json(request_params[:rest_args].strip, symbolize: true)
31
33
  end
32
34
  end
33
35
 
@@ -0,0 +1,19 @@
1
+ module SidekiqAdhocJob
2
+ module Strategies
3
+ class ActiveJob
4
+ include SidekiqAdhocJob::Strategy
5
+
6
+ def worker_class?(klass)
7
+ klass.superclass&.name == 'ActiveJob::Base'
8
+ end
9
+
10
+ def get_queue_name(klass_name)
11
+ klass_name.queue_name
12
+ end
13
+
14
+ def perform_async(klass, *params)
15
+ klass.perform_later(*params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module SidekiqAdhocJob
2
+ module Strategies
3
+ class Default
4
+ include SidekiqAdhocJob::Strategy
5
+
6
+ def worker_class?(klass)
7
+ klass.included_modules.include?(Sidekiq::Worker)
8
+ end
9
+
10
+ def get_queue_name(klass_name)
11
+ klass_name.sidekiq_options['queue']
12
+ end
13
+
14
+ def perform_async(klass, *params)
15
+ klass.perform_async(*params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module SidekiqAdhocJob
2
+ module Strategies
3
+ class RailsApplicationJob
4
+ include SidekiqAdhocJob::Strategy
5
+
6
+ def worker_class?(klass)
7
+ klass.superclass&.name == 'ApplicationJob'
8
+ end
9
+
10
+ def get_queue_name(klass_name)
11
+ klass_name.queue_name
12
+ end
13
+
14
+ def perform_async(klass, *params)
15
+ klass.perform_later(*params)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,43 @@
1
+ module SidekiqAdhocJob
2
+ module Strategy
3
+ def self.included(base)
4
+ SidekiqAdhocJob.strategies << base
5
+
6
+ base.extend ClassMethods
7
+ base.class_eval do
8
+ end
9
+ end
10
+
11
+ attr_reader :module_names, :worker_klasses
12
+
13
+ StringUtil ||= SidekiqAdhocJob::Utils::String
14
+
15
+ def initialize(module_names)
16
+ @module_names = module_names
17
+ @worker_klasses = {}
18
+ end
19
+
20
+ def load
21
+ ObjectSpace.each_object(Class).each do |klass|
22
+ next unless klass
23
+
24
+ if worker_class?(klass) && allowed_namespace?(klass.name, allowlist: module_names)
25
+ @worker_klasses[worker_path_name(klass.name)] = klass
26
+ end
27
+ end
28
+ end
29
+
30
+ def allowed_namespace?(class_name, allowlist:)
31
+ return true if allowlist.empty? || allowlist.include?('Module') # allow any namespace
32
+
33
+ allowlist.any? { |prefix| class_name.start_with?(prefix) }
34
+ end
35
+
36
+ def worker_path_name(worker_name)
37
+ Utils::String.underscore(worker_name).gsub('/', '_')
38
+ end
39
+
40
+ module ClassMethods
41
+ end
42
+ end
43
+ end
@@ -1,4 +1,5 @@
1
1
  # References: https://github.com/hanami/utils/blob/master/lib/hanami/utils/string.rb
2
+ # https://github.com/omniauth/omniauth/blob/cc0f5522621b4a372f4dff0aa608822aa082cb60/lib/omniauth.rb#L156
2
3
  module SidekiqAdhocJob
3
4
  module Utils
4
5
  class String
@@ -75,7 +76,15 @@ module SidekiqAdhocJob
75
76
  constant
76
77
  end
77
78
 
78
- def self.parse(input)
79
+ def self.camelize(word, first_letter_in_uppercase = true)
80
+ if first_letter_in_uppercase
81
+ word.to_s.gsub(%r{/(.?)}) { '::' + Regexp.last_match[1].upcase }.gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase }
82
+ else
83
+ word.first + self.camelize(word)[1..-1]
84
+ end
85
+ end
86
+
87
+ def self.parse(input, symbolize: false)
79
88
  return unless input
80
89
 
81
90
  if input == 'true'
@@ -88,7 +97,7 @@ module SidekiqAdhocJob
88
97
  i
89
98
  elsif (f = parse_float(input))
90
99
  f
91
- elsif (j = parse_json(input))
100
+ elsif (j = parse_json(input, symbolize: symbolize))
92
101
  j
93
102
  else
94
103
  input
@@ -107,8 +116,8 @@ module SidekiqAdhocJob
107
116
  nil
108
117
  end
109
118
 
110
- def self.parse_json(input)
111
- JSON.parse(input)
119
+ def self.parse_json(input, symbolize: false)
120
+ JSON.parse(input, symbolize_names: symbolize)
112
121
  rescue JSON::ParserError => _e
113
122
  nil
114
123
  end
@@ -1,3 +1,3 @@
1
1
  module SidekiqAdhocJob
2
- VERSION = '0.1.5'.freeze
2
+ VERSION = '0.3.1'.freeze
3
3
  end
@@ -4,7 +4,7 @@ module SidekiqAdhocJob
4
4
  class JobPresenter
5
5
  include Sidekiq::WebHelpers
6
6
 
7
- attr_reader :name, :path_name, :queue, :has_rest_args, :args
7
+ attr_reader :name, :path_name, :queue, :required_args, :optional_args, :has_rest_args
8
8
 
9
9
  StringUtil ||= ::SidekiqAdhocJob::Utils::String
10
10
 
@@ -16,7 +16,6 @@ module SidekiqAdhocJob
16
16
  @required_args = args[:req] || []
17
17
  @optional_args = args[:opt] || []
18
18
  @has_rest_args = !!args[:rest]
19
- @args = @required_args + @optional_args
20
19
  end
21
20
 
22
21
  # Builds the presenter instances for the schedule hash
@@ -38,7 +37,7 @@ module SidekiqAdhocJob
38
37
  end
39
38
 
40
39
  def self.convert_klass_name_to_presenter(path_name, klass_name)
41
- queue = klass_name.sidekiq_options['queue']
40
+ queue = SidekiqAdhocJob.config.strategy.get_queue_name(klass_name)
42
41
  class_inspector = SidekiqAdhocJob::Utils::ClassInspector.new(klass_name)
43
42
  args = class_inspector.parameters(:perform)
44
43
  new(klass_name, path_name, queue, args)
@@ -1,7 +1,8 @@
1
1
  en:
2
2
  adhoc_jobs: Adhoc Jobs
3
3
  adhoc_jobs_actions: Actions
4
- adhoc_jobs_arguments: Required Arguments
4
+ adhoc_jobs_required_arguments: Required Arguments
5
+ adhoc_jobs_optional_arguments: Optional Arguments
5
6
  adhoc_jobs_go_back: Go Back
6
7
  adhoc_jobs_has_rest_arguments: Has Rest Arguments
7
8
  adhoc_jobs_name: Job Name
@@ -6,7 +6,8 @@
6
6
  <tr>
7
7
  <th><%= t('adhoc_jobs_name') %></th>
8
8
  <th><%= t('adhoc_jobs_queue') %></th>
9
- <th><%= t('adhoc_jobs_arguments') %></th>
9
+ <th><%= t('adhoc_jobs_required_arguments') %></th>
10
+ <th><%= t('adhoc_jobs_optional_arguments') %></th>
10
11
  <th><%= t('adhoc_jobs_has_rest_arguments') %></th>
11
12
  <th><%= t('adhoc_jobs_actions') %></th>
12
13
  </tr>
@@ -17,7 +18,8 @@
17
18
  <tr>
18
19
  <td><%= job.name %></td>
19
20
  <td><%= job.queue %></td>
20
- <td><%= job.args.join(', ') %></td>
21
+ <td><%= job.required_args.join(', ') %></td>
22
+ <td><%= job.optional_args.join(', ') %></td>
21
23
  <td><%= job.has_rest_args %></td>
22
24
  <td class="text-center">
23
25
  <a class="btn btn-warn btn-xs" href="<%= root_path %>adhoc-jobs/<%= URI.escape(job.path_name) %>">
@@ -1,11 +1,13 @@
1
1
  <h3><%= t('adhoc_jobs') %></h3>
2
2
 
3
+ <h4><%= SidekiqAdhocJob::Utils::String.classify(@presented_job.path_name) %></h4>
4
+
3
5
  <form method="POST" action="<%= root_path %>adhoc-jobs/<%= URI.escape(@presented_job.path_name) %>/schedule">
4
6
  <input type="hidden" name="authenticity_token" value="<%= @csrf_token %>" />
5
- <% if @presented_job.args.empty? && !@presented_job.has_rest_args %>
7
+ <% if @presented_job.required_args.empty? && @presented_job.optional_args.empty? && !@presented_job.has_rest_args %>
6
8
  <p>No job arguments</p>
7
9
  <% else %>
8
- <% @presented_job.args.each do |arg| %>
10
+ <% @presented_job.required_args.each do |arg| %>
9
11
  <div class="form-group row">
10
12
  <label class="col-sm-2 col-form-label" for="<%= arg %>">*<%= arg %>:</label>
11
13
  <div class="col-sm-4">
@@ -13,11 +15,19 @@
13
15
  </div>
14
16
  </div>
15
17
  <% end %>
18
+ <% @presented_job.optional_args.each do |arg| %>
19
+ <div class="form-group row">
20
+ <label class="col-sm-2 col-form-label" for="<%= arg %>"><%= arg %>:</label>
21
+ <div class="col-sm-4">
22
+ <input class="form-control" type="text" name="<%= arg %>" id="<%= arg %>"/>
23
+ </div>
24
+ </div>
25
+ <% end %>
16
26
  <% if @presented_job.has_rest_args %>
17
27
  <div class="form-group row">
18
- <label class="col-sm-2 col-form-label" for="rest_args">*Rest arguments (please separate each argument by comma):</label>
28
+ <label class="col-sm-2 col-form-label" for="rest_args">Rest arguments (please provide a json string representing the arguments):</label>
19
29
  <div class="col-sm-4">
20
- <input class="form-control" type="text" name="rest_args" id="rest_args" required/>
30
+ <input class="form-control" type="text" name="rest_args" id="rest_args"/>
21
31
  </div>
22
32
  </div>
23
33
  <% end %>
@@ -1,17 +1,11 @@
1
1
  module SidekiqAdhocJob
2
2
  class WorkerClassesLoader
3
-
4
- StringUtil ||= Utils::String
5
-
6
3
  @_worker_klasses = {}
7
4
 
8
- def self.load(module_names)
9
- module_consts = module_names.map { |name| StringUtil.constantize(name.to_s) }
10
- module_consts.each do |module_const|
11
- module_const.constants.each do |sub_module_const_sym|
12
- load_workers(module_const, sub_module_const_sym, @_worker_klasses)
13
- end
14
- end
5
+ def self.load(module_names, strategy:, load_paths:)
6
+ require_files(load_paths)
7
+ strategy.load
8
+ @_worker_klasses = strategy.worker_klasses
15
9
  end
16
10
 
17
11
  def self.worker_klasses
@@ -22,27 +16,8 @@ module SidekiqAdhocJob
22
16
  @_worker_klasses[path_name]
23
17
  end
24
18
 
25
- def self.load_workers(parent_module_const, module_sym, workers)
26
- qualified_name = module_sym.to_s
27
-
28
- module_const = begin
29
- StringUtil.constantize(qualified_name)
30
- rescue NameError => _e
31
- qualified_name = [parent_module_const, module_sym].compact.join('::')
32
- begin
33
- StringUtil.constantize(qualified_name)
34
- rescue NameError => _e
35
- nil
36
- end
37
- end
38
- return unless module_const && module_const.is_a?(Class)
39
-
40
- if module_const.include?(Sidekiq::Worker)
41
- path_name = StringUtil.underscore(qualified_name).gsub('/', '_')
42
- workers[path_name] = module_const
43
- return
44
- end
19
+ def self.require_files(load_paths)
20
+ Dir[File.join("", load_paths)].each { |path| require path } unless load_paths.empty?
45
21
  end
46
-
47
22
  end
48
23
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sidekiq_adhoc_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Goh Khoon Hiang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-07-08 00:00:00.000000000 Z
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.1
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.1
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +58,14 @@ dependencies:
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 3.8.0
61
+ version: 3.10.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 3.8.0
68
+ version: 3.10.0
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rack-test
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -86,28 +86,28 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: 0.20.0
89
+ version: 0.26.0
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: 0.20.0
96
+ version: 0.26.0
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: sidekiq
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - "<"
102
102
  - !ruby/object:Gem::Version
103
- version: 5.2.7
103
+ version: '7'
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - "<"
109
109
  - !ruby/object:Gem::Version
110
- version: 5.2.7
110
+ version: '7'
111
111
  description: Trigger jobs adhoc from Sidekiq web admin
112
112
  email:
113
113
  - gohkhoonhiang@gmail.com
@@ -117,6 +117,10 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - lib/sidekiq_adhoc_job.rb
119
119
  - lib/sidekiq_adhoc_job/services/schedule_adhoc_job.rb
120
+ - lib/sidekiq_adhoc_job/strategies/active_job.rb
121
+ - lib/sidekiq_adhoc_job/strategies/default.rb
122
+ - lib/sidekiq_adhoc_job/strategies/rails_application_job.rb
123
+ - lib/sidekiq_adhoc_job/strategy.rb
120
124
  - lib/sidekiq_adhoc_job/utils/class_inspector.rb
121
125
  - lib/sidekiq_adhoc_job/utils/string.rb
122
126
  - lib/sidekiq_adhoc_job/version.rb
@@ -141,16 +145,16 @@ require_paths:
141
145
  - lib
142
146
  required_ruby_version: !ruby/object:Gem::Requirement
143
147
  requirements:
144
- - - ">="
148
+ - - "~>"
145
149
  - !ruby/object:Gem::Version
146
- version: 2.6.0
150
+ version: '2.6'
147
151
  required_rubygems_version: !ruby/object:Gem::Requirement
148
152
  requirements:
149
153
  - - ">="
150
154
  - !ruby/object:Gem::Version
151
155
  version: '0'
152
156
  requirements: []
153
- rubygems_version: 3.0.4
157
+ rubygems_version: 3.0.8
154
158
  signing_key:
155
159
  specification_version: 4
156
160
  summary: Trigger jobs adhoc from Sidekiq web admin