sidekiq_adhoc_job 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cbb78def72673141d39f88a5cdd7b3142da526620ce4ec42829cac57cc35f398
4
+ data.tar.gz: ae4d22cb3bcaeef550515011c282368bd6f6ccb75b93a9b6fc397af87cdd9662
5
+ SHA512:
6
+ metadata.gz: 50288dad7f7287ceed184e0327febe69b26eccf994a81f335819aa6b15bc9c8c300e7da3c373dce6ea3de3beb5b4cabf0539c25765dab3659cda63041d97cb9e
7
+ data.tar.gz: e6f3e09e7c731034059bfc6085219a20c401385d65b52fd57d659ab739a0d6d4c41d8a1fd330d47256ebb62b9d5e7c841711383897ed36db0ebfc6ed8988b541
@@ -0,0 +1,32 @@
1
+ module SidekiqAdhocJob
2
+ class ScheduleAdhocJob
3
+
4
+ StringUtil ||= ::SidekiqAdhocJob::Utils::String
5
+
6
+ def initialize(job_name, request_params)
7
+ @request_params = request_params.inject({}) do |acc, (k, v)|
8
+ acc[k.to_sym] = v
9
+ acc
10
+ end
11
+ @worker_klass = WorkerClassesLoader.find_worker_klass(job_name)
12
+ parse_params
13
+ end
14
+
15
+ def call
16
+ worker_klass.perform_async(*worker_params)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :request_params, :worker_klass, :allowed_params, :worker_params
22
+
23
+ def parse_params
24
+ @allowed_params = worker_klass.new.method(:perform).parameters.reject { |type, _| type == :rest }.flat_map(&:last)
25
+ @worker_params = allowed_params.map { |key| StringUtil.parse(request_params[key]) }
26
+ if !!request_params[:rest_args] && !request_params[:rest_args].empty?
27
+ @worker_params += request_params[:rest_args].split(',').map { |arg| StringUtil.parse(arg.strip) }
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,108 @@
1
+ # References: https://github.com/hanami/utils/blob/master/lib/hanami/utils/string.rb
2
+ module SidekiqAdhocJob
3
+ module Utils
4
+ class String
5
+
6
+ EMPTY_STRING ||= ''.freeze
7
+ CLASSIFY_SEPARATOR ||= '_'.freeze
8
+ NAMESPACE_SEPARATOR ||= '::'.freeze
9
+ UNDERSCORE_SEPARATOR ||= '/'.freeze
10
+ UNDERSCORE_DIVISION_TARGET ||= '\1_\2'.freeze
11
+ DASHERIZE_SEPARATOR ||= '-'.freeze
12
+ CLASSIFY_WORD_SEPARATOR ||= /#{CLASSIFY_SEPARATOR}|#{NAMESPACE_SEPARATOR}|#{UNDERSCORE_SEPARATOR}|#{DASHERIZE_SEPARATOR}/.freeze
13
+
14
+ # Return a CamelCase version of the string
15
+ # If the given string is a file name, it will convert each file directory into a CamelCase namespace
16
+ #
17
+ # @see https://github.com/hanami/utils/blob/92ef4464f7ae3e5acba4b8fadc1c8225a81b9b76/lib/hanami/utils/string.rb#L223
18
+ #
19
+ # @param input [::String] the input
20
+ #
21
+ # @return [::String] the transformed string
22
+ #
23
+ # @since 0.1.0
24
+ #
25
+ # @example
26
+ # require 'sidekiq_adhoc_job/utils/string'
27
+ #
28
+ # SidekiqAdhocJob::Utils::String.classify('sidekiq_adhoc_job') # => 'SidekiqAdhocJob'
29
+ # SidekiqAdhocJob::Utils::String.classify('sidekiq_adhoc_job/utils/string') # => 'SidekiqAdhocJob::Utils::String'
30
+ def self.classify(input)
31
+ string = ::String.new(input.to_s)
32
+ words = underscore(string).split(CLASSIFY_WORD_SEPARATOR).map!(&:capitalize)
33
+ delimiters = underscore(string).scan(CLASSIFY_WORD_SEPARATOR)
34
+
35
+ delimiters.map! do |delimiter|
36
+ delimiter == CLASSIFY_SEPARATOR ? EMPTY_STRING : NAMESPACE_SEPARATOR
37
+ end
38
+
39
+ words.zip(delimiters).join
40
+ end
41
+
42
+ # Return a downcased and underscore separated version of the string
43
+ # If the given string is a namespaced class name, it will convert the namespace separator :: into a file path separator /
44
+ #
45
+ # @see https://github.com/hanami/utils/blob/92ef4464f7ae3e5acba4b8fadc1c8225a81b9b76/lib/hanami/utils/string.rb#L250
46
+ #
47
+ # @param input [::String] the input
48
+ #
49
+ # @return [::String] the transformed string
50
+ #
51
+ # @since 0.1.0
52
+ #
53
+ # @example
54
+ # require 'sidekiq_adhoc_job/utils/string'
55
+ #
56
+ # SidekiqAdhocJob::Utils::String.underscore('SidekiqAdhocJob') # => 'sidekiq_adhoc_job'
57
+ # SidekiqAdhocJob::Utils::String.underscore('SidekiqAdhocJob::Utils::String') # => 'sidekiq_adhoc_job/utils/string'
58
+ def self.underscore(input)
59
+ string = ::String.new(input.to_s)
60
+ string.gsub!(NAMESPACE_SEPARATOR, UNDERSCORE_SEPARATOR)
61
+ string.gsub!(/([A-Z\d]+)([A-Z][a-z])/, UNDERSCORE_DIVISION_TARGET)
62
+ string.gsub!(/([a-z\d])([A-Z])/, UNDERSCORE_DIVISION_TARGET)
63
+ string.gsub!(/[[:space:]]|\-/, UNDERSCORE_DIVISION_TARGET)
64
+ string.downcase
65
+ end
66
+
67
+ def self.constantize(input)
68
+ names = input.split('::')
69
+ names.shift if names.empty? || names.first.empty?
70
+
71
+ constant = Object
72
+ names.each do |name|
73
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
74
+ end
75
+ constant
76
+ end
77
+
78
+ def self.parse(input)
79
+ return unless input
80
+
81
+ if input == 'true'
82
+ true
83
+ elsif input == 'false'
84
+ false
85
+ elsif (i = parse_integer(input))
86
+ i
87
+ elsif (f = parse_float(input))
88
+ f
89
+ else
90
+ input
91
+ end
92
+ end
93
+
94
+ def self.parse_integer(input)
95
+ Integer(input)
96
+ rescue ArgumentError => _e
97
+ nil
98
+ end
99
+
100
+ def self.parse_float(input)
101
+ Float(input)
102
+ rescue ArgumentError => _e
103
+ nil
104
+ end
105
+
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ module SidekiqAdhocJob
2
+ VERSION = '0.1.2'.freeze
3
+ end
@@ -0,0 +1,56 @@
1
+ # References: https://github.com/moove-it/sidekiq-scheduler/blob/master/lib/sidekiq-scheduler/job_presenter.rb
2
+ module SidekiqAdhocJob
3
+ module Web
4
+ class JobPresenter
5
+ include Sidekiq::WebHelpers
6
+
7
+ attr_reader :name, :path_name, :queue, :required_args, :optional_args, :has_rest_args, :args
8
+
9
+ StringUtil ||= ::SidekiqAdhocJob::Utils::String
10
+
11
+ # args: { req: [], opt: [] }
12
+ def initialize(name, path_name, queue, args)
13
+ @name = name
14
+ @path_name = path_name
15
+ @queue = queue
16
+ @required_args = args[:req] || []
17
+ @optional_args = args[:opt] || []
18
+ @has_rest_args = !!args[:rest]
19
+ @args = @required_args + @optional_args
20
+ end
21
+
22
+ # Builds the presenter instances for the schedule hash
23
+ #
24
+ # @param
25
+ # @return [Array<JobPresenter>] an array with the instances of presenters
26
+ def self.build_collection
27
+ WorkerClassesLoader.worker_klasses.map do |path_name, worker_klass|
28
+ convert_klass_name_to_presenter(path_name, worker_klass)
29
+ end
30
+ end
31
+
32
+ def self.find(path_name)
33
+ klass_name = WorkerClassesLoader.find_worker_klass(path_name)
34
+
35
+ return unless klass_name
36
+
37
+ convert_klass_name_to_presenter(path_name, klass_name)
38
+ end
39
+
40
+ def self.convert_klass_name_to_presenter(path_name, klass_name)
41
+ klass_obj = klass_name.new
42
+ queue = klass_name.sidekiq_options['queue']
43
+ args = klass_obj
44
+ .method(:perform)
45
+ .parameters
46
+ .group_by { |type, _| type }
47
+ .inject({}) do |acc, (type, params)|
48
+ acc[type] = params.map(&:last)
49
+ acc
50
+ end
51
+ new(klass_name, path_name, queue, args)
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,11 @@
1
+ en:
2
+ adhoc_jobs: Adhoc Jobs
3
+ adhoc_jobs_actions: Actions
4
+ adhoc_jobs_go_back: Go Back
5
+ adhoc_jobs_has_rest_arguments: Has Rest Arguments
6
+ adhoc_jobs_name: Job Name
7
+ adhoc_jobs_optional_arguments: Optional Arguments
8
+ adhoc_jobs_queue: Job Queue
9
+ adhoc_jobs_required_arguments: Required Arguments
10
+ adhoc_jobs_run_job: Run Job
11
+ adhoc_jobs_view_job: View Job
@@ -0,0 +1,17 @@
1
+ module SidekiqAdhocJob
2
+ module Web
3
+ module Jobs
4
+ class Index
5
+
6
+ def self.register(app)
7
+ app.get '/adhoc-jobs' do
8
+ @presented_jobs = SidekiqAdhocJob::Web::JobPresenter.build_collection
9
+
10
+ erb File.read(File.join(VIEW_PATH, 'jobs/index.html.erb'))
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module SidekiqAdhocJob
2
+ module Web
3
+ module Jobs
4
+ class Schedule
5
+
6
+ def self.register(app)
7
+ app.post '/adhoc-jobs/:name/schedule' do
8
+ SidekiqAdhocJob::ScheduleAdhocJob.new(params[:name], request.params).call
9
+ redirect "#{root_path}adhoc-jobs"
10
+ end
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,21 @@
1
+ module SidekiqAdhocJob
2
+ module Web
3
+ module Jobs
4
+ class Show
5
+
6
+ def self.register(app)
7
+ app.get '/adhoc-jobs/:name' do
8
+ @csrf_token = env['rack.session'][:csrf]
9
+ @presented_job = SidekiqAdhocJob::Web::JobPresenter.find(params[:name])
10
+ if @presented_job
11
+ erb File.read(File.join(VIEW_PATH, 'jobs/show.html.erb'))
12
+ else
13
+ redirect "#{root_path}adhoc-jobs"
14
+ end
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ <h3><%= t('adhoc_jobs') %></h3>
2
+
3
+ <div class="table_container">
4
+ <table class="table table-hover table-bordered table-striped table-white">
5
+ <thead>
6
+ <tr>
7
+ <th><%= t('adhoc_jobs_name') %></th>
8
+ <th><%= t('adhoc_jobs_queue') %></th>
9
+ <th><%= t('adhoc_jobs_required_arguments') %></th>
10
+ <th><%= t('adhoc_jobs_optional_arguments') %></th>
11
+ <th><%= t('adhoc_jobs_has_rest_arguments') %></th>
12
+ <th><%= t('adhoc_jobs_actions') %></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+ <% @presented_jobs.each do |job| %>
18
+ <tr>
19
+ <td><%= job.name %></td>
20
+ <td><%= job.queue %></td>
21
+ <td><%= job.required_args.join(', ') %></td>
22
+ <td><%= job.optional_args.join(', ') %></td>
23
+ <td><%= job.has_rest_args %></td>
24
+ <td class="text-center">
25
+ <a class="btn btn-warn btn-xs" href="<%= root_path %>adhoc-jobs/<%= URI.escape(job.path_name) %>">
26
+ <%= t('adhoc_jobs_view_job') %>
27
+ </a>
28
+ </td>
29
+ </tr>
30
+ <% end %>
31
+ </tbody>
32
+ </table>
33
+ </div>
@@ -0,0 +1,39 @@
1
+ <h3><%= t('adhoc_jobs') %></h3>
2
+
3
+ <form method="POST" action="<%= root_path %>adhoc-jobs/<%= URI.escape(@presented_job.path_name) %>/schedule">
4
+ <input type="hidden" name="authenticity_token" value="<%= @csrf_token %>" />
5
+ <% if @presented_job.args.empty? && !@presented_job.has_rest_args %>
6
+ <p>No job arguments</p>
7
+ <% else %>
8
+ <% @presented_job.required_args.each do |arg| %>
9
+ <div class="form-group row">
10
+ <label class="col-sm-2 col-form-label" for="<%= arg %>">*<%= arg %>:</label>
11
+ <div class="col-sm-4">
12
+ <input class="form-control" type="text" name="<%= arg %>" id="<%= arg %>" required/>
13
+ </div>
14
+ </div>
15
+ <% end %>
16
+ <% @presented_job.optional_args.each do |arg| %>
17
+ <div class="form-group row">
18
+ <label class="col-sm-2 col-form-label" for="<%= arg %>"><%= arg %>:</label>
19
+ <div class="col-sm-4">
20
+ <input class="form-control" type="text" name="<%= arg %>" id="<%= arg %>"/>
21
+ </div>
22
+ </div>
23
+ <% end %>
24
+ <% if @presented_job.has_rest_args %>
25
+ <div class="form-group row">
26
+ <label class="col-sm-2 col-form-label" for="rest_args">*Rest arguments (please separate each argument by comma):</label>
27
+ <div class="col-sm-4">
28
+ <input class="form-control" type="text" name="rest_args" id="rest_args" required/>
29
+ </div>
30
+ </div>
31
+ <% end %>
32
+ <% end %>
33
+ <div class="form-group row">
34
+ <div class="col-sm-4">
35
+ <button type="submit" class="btn btn-danger"><%= t('adhoc_jobs_run_job') %></button>
36
+ <a class="btn" href="<%= root_path %>adhoc-jobs"><%= t('adhoc_jobs_go_back') %></a>
37
+ </div>
38
+ </div>
39
+ </form>
@@ -0,0 +1,26 @@
1
+ require 'pathname'
2
+
3
+ ROUTE_PATH ||= File.expand_path('web/routes', __dir__)
4
+
5
+ module SidekiqAdhocJob
6
+ module Web
7
+ VIEW_PATH ||= File.expand_path('web/templates', __dir__)
8
+
9
+ StringUtil ||= ::SidekiqAdhocJob::Utils::String
10
+
11
+ def self.registered(app)
12
+ Dir[File.join(ROUTE_PATH, '**/*.rb')].each do |file_name|
13
+ relative_path = ::Pathname.new(file_name).relative_path_from(ROUTE_PATH)
14
+ module_name = StringUtil.classify(File.dirname(relative_path))
15
+ klass_name = StringUtil.classify(File.basename(relative_path, '.rb'))
16
+ namespaced_klass_name = StringUtil.constantize("SidekiqAdhocJob::Web::#{module_name}::#{klass_name}")
17
+ namespaced_klass_name.register(app)
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+
24
+ Dir[File.join(ROUTE_PATH, '**/*.rb')].each do |file_name|
25
+ require_relative file_name
26
+ end
@@ -0,0 +1,52 @@
1
+ module SidekiqAdhocJob
2
+ class WorkerClassesLoader
3
+
4
+ VALID_QUALIFIED_CLASS_NAME ||= /\A(([A-Z]{1}[a-z]+)(::)*)+\z/
5
+ VALID_WORKER_CLASS_NAME ||= /^.+[^(::)]+Worker$/
6
+
7
+ StringUtil ||= Utils::String
8
+
9
+ @_worker_klasses = {}
10
+
11
+ def self.load(module_names)
12
+ module_consts = module_names.map { |name| StringUtil.constantize(name.to_s) }
13
+ module_consts.each do |module_const|
14
+ module_const.constants.each do |sub_module_const_sym|
15
+ load_workers(module_const, sub_module_const_sym, @_worker_klasses)
16
+ end
17
+ end
18
+ end
19
+
20
+ def self.worker_klasses
21
+ @_worker_klasses
22
+ end
23
+
24
+ def self.find_worker_klass(path_name)
25
+ @_worker_klasses[path_name]
26
+ end
27
+
28
+ def self.load_workers(parent_module_const, module_sym, workers)
29
+ qualified_name = module_sym.to_s
30
+ return unless VALID_QUALIFIED_CLASS_NAME.match?(qualified_name)
31
+
32
+ module_const = begin
33
+ StringUtil.constantize(qualified_name)
34
+ rescue NameError => _e
35
+ qualified_name = [parent_module_const, module_sym].compact.join('::')
36
+ begin
37
+ StringUtil.constantize(qualified_name)
38
+ rescue NameError => _e
39
+ nil
40
+ end
41
+ end
42
+ return unless module_const && module_const.is_a?(Class)
43
+
44
+ if VALID_WORKER_CLASS_NAME.match?(qualified_name)
45
+ path_name = StringUtil.underscore(qualified_name).gsub('/', '_')
46
+ workers[path_name] = module_const
47
+ return
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,45 @@
1
+ require 'sidekiq'
2
+ require 'sidekiq/web'
3
+
4
+ require 'sidekiq_adhoc_job/utils/string'
5
+ require 'sidekiq_adhoc_job/worker_classes_loader'
6
+ require 'sidekiq_adhoc_job/web/job_presenter'
7
+ require 'sidekiq_adhoc_job/services/schedule_adhoc_job'
8
+ require 'sidekiq_adhoc_job/web'
9
+
10
+ module SidekiqAdhocJob
11
+
12
+ InvalidConfigurationError ||= Class.new(RuntimeError)
13
+
14
+ def self.configure
15
+ @_config = Configuration.new
16
+ yield @_config
17
+ end
18
+
19
+ def self.config
20
+ @_config
21
+ end
22
+
23
+ def self.init
24
+ raise InvalidConfigurationError, 'Must configure before init' unless @_config&.configured?
25
+
26
+ SidekiqAdhocJob::WorkerClassesLoader.load(@_config.module_names)
27
+
28
+ Sidekiq::Web.register(SidekiqAdhocJob::Web)
29
+ Sidekiq::Web.tabs['adhoc_jobs'] = 'adhoc-jobs'
30
+ Sidekiq::Web.locales << File.expand_path('sidekiq_adhoc_job/web/locales', __dir__)
31
+ end
32
+
33
+ class Configuration
34
+ attr_accessor :module_names
35
+
36
+ def initialize
37
+ @module_names = []
38
+ end
39
+
40
+ def configured?
41
+ !@module_names.empty?
42
+ end
43
+ end
44
+
45
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sidekiq_adhoc_job
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - Goh Khoon Hiang
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-06-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 2.0.1
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 2.0.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 12.3.2
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 12.3.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.8.0
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.8.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rack-test
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: mock_redis
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.20.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.20.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: sidekiq
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: 5.2.7
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: 5.2.7
111
+ description: Trigger jobs adhoc from Sidekiq web admin
112
+ email:
113
+ - gohkhoonhiang@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - lib/sidekiq_adhoc_job.rb
119
+ - lib/sidekiq_adhoc_job/services/schedule_adhoc_job.rb
120
+ - lib/sidekiq_adhoc_job/utils/string.rb
121
+ - lib/sidekiq_adhoc_job/version.rb
122
+ - lib/sidekiq_adhoc_job/web.rb
123
+ - lib/sidekiq_adhoc_job/web/job_presenter.rb
124
+ - lib/sidekiq_adhoc_job/web/locales/en.yml
125
+ - lib/sidekiq_adhoc_job/web/routes/jobs/index.rb
126
+ - lib/sidekiq_adhoc_job/web/routes/jobs/schedule.rb
127
+ - lib/sidekiq_adhoc_job/web/routes/jobs/show.rb
128
+ - lib/sidekiq_adhoc_job/web/templates/jobs/index.html.erb
129
+ - lib/sidekiq_adhoc_job/web/templates/jobs/show.html.erb
130
+ - lib/sidekiq_adhoc_job/worker_classes_loader.rb
131
+ homepage: https://github.com/gohkhoonhiang/sidekiq_adhoc_job
132
+ licenses:
133
+ - MIT
134
+ metadata:
135
+ allowed_push_host: https://rubygems.org
136
+ post_install_message:
137
+ rdoc_options: []
138
+ require_paths:
139
+ - lib/sidekiq_adhoc_job
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: 2.6.0
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubygems_version: 3.0.3
153
+ signing_key:
154
+ specification_version: 4
155
+ summary: Trigger jobs adhoc from Sidekiq web admin
156
+ test_files: []