wurk 0.0.1
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 +7 -0
- data/CHANGELOG.md +43 -0
- data/CONTRIBUTING.md +73 -0
- data/LICENSE +21 -0
- data/README.md +137 -0
- data/SECURITY.md +39 -0
- data/app/controllers/wurk/api/pagination.rb +67 -0
- data/app/controllers/wurk/api/serializers.rb +131 -0
- data/app/controllers/wurk/api_controller.rb +248 -0
- data/app/controllers/wurk/application_controller.rb +7 -0
- data/app/controllers/wurk/dashboard_controller.rb +48 -0
- data/config/locales/en.yml +15 -0
- data/config/routes.rb +34 -0
- data/exe/wurk +22 -0
- data/lib/active_job/queue_adapters/wurk_adapter.rb +96 -0
- data/lib/generators/wurk/install/install_generator.rb +22 -0
- data/lib/generators/wurk/install/templates/wurk.rb +16 -0
- data/lib/wurk/active_job/wrapper.rb +32 -0
- data/lib/wurk/api/fast.rb +78 -0
- data/lib/wurk/batch/buffer.rb +26 -0
- data/lib/wurk/batch/callback_job.rb +37 -0
- data/lib/wurk/batch/callbacks.rb +176 -0
- data/lib/wurk/batch/client_middleware.rb +27 -0
- data/lib/wurk/batch/death_handler.rb +39 -0
- data/lib/wurk/batch/empty.rb +21 -0
- data/lib/wurk/batch/server_middleware.rb +62 -0
- data/lib/wurk/batch/status.rb +140 -0
- data/lib/wurk/batch.rb +351 -0
- data/lib/wurk/batch_set.rb +67 -0
- data/lib/wurk/capsule.rb +176 -0
- data/lib/wurk/cli.rb +349 -0
- data/lib/wurk/client/buffered.rb +372 -0
- data/lib/wurk/client.rb +330 -0
- data/lib/wurk/compat.rb +136 -0
- data/lib/wurk/component.rb +136 -0
- data/lib/wurk/configuration.rb +373 -0
- data/lib/wurk/context.rb +35 -0
- data/lib/wurk/cron.rb +636 -0
- data/lib/wurk/dashboard_manifest.rb +39 -0
- data/lib/wurk/dead_set.rb +78 -0
- data/lib/wurk/deploy.rb +91 -0
- data/lib/wurk/embedded.rb +94 -0
- data/lib/wurk/encryption.rb +276 -0
- data/lib/wurk/engine.rb +81 -0
- data/lib/wurk/fetcher/reaper.rb +264 -0
- data/lib/wurk/fetcher/reliable.rb +138 -0
- data/lib/wurk/fetcher.rb +11 -0
- data/lib/wurk/health.rb +193 -0
- data/lib/wurk/heartbeat.rb +211 -0
- data/lib/wurk/iterable_job.rb +292 -0
- data/lib/wurk/job/options.rb +70 -0
- data/lib/wurk/job.rb +33 -0
- data/lib/wurk/job_logger.rb +68 -0
- data/lib/wurk/job_record.rb +156 -0
- data/lib/wurk/job_retry.rb +320 -0
- data/lib/wurk/job_set.rb +212 -0
- data/lib/wurk/job_util.rb +162 -0
- data/lib/wurk/keys.rb +52 -0
- data/lib/wurk/launcher.rb +289 -0
- data/lib/wurk/leader.rb +221 -0
- data/lib/wurk/limiter/base.rb +138 -0
- data/lib/wurk/limiter/bucket.rb +80 -0
- data/lib/wurk/limiter/concurrent.rb +132 -0
- data/lib/wurk/limiter/leaky.rb +91 -0
- data/lib/wurk/limiter/points.rb +89 -0
- data/lib/wurk/limiter/server_middleware.rb +77 -0
- data/lib/wurk/limiter/unlimited.rb +48 -0
- data/lib/wurk/limiter/window.rb +80 -0
- data/lib/wurk/limiter.rb +255 -0
- data/lib/wurk/logger.rb +81 -0
- data/lib/wurk/lua/loader.rb +53 -0
- data/lib/wurk/lua.rb +187 -0
- data/lib/wurk/manager.rb +132 -0
- data/lib/wurk/metrics/history.rb +151 -0
- data/lib/wurk/metrics/query.rb +173 -0
- data/lib/wurk/metrics/rollup.rb +169 -0
- data/lib/wurk/metrics/statsd.rb +197 -0
- data/lib/wurk/metrics.rb +7 -0
- data/lib/wurk/middleware/chain.rb +128 -0
- data/lib/wurk/middleware/current_attributes.rb +87 -0
- data/lib/wurk/middleware/expiry.rb +50 -0
- data/lib/wurk/middleware/i18n.rb +63 -0
- data/lib/wurk/middleware/interrupt_handler.rb +45 -0
- data/lib/wurk/middleware/poison_pill.rb +149 -0
- data/lib/wurk/middleware.rb +34 -0
- data/lib/wurk/process_set.rb +243 -0
- data/lib/wurk/processor.rb +247 -0
- data/lib/wurk/queue.rb +108 -0
- data/lib/wurk/queues.rb +80 -0
- data/lib/wurk/rails.rb +9 -0
- data/lib/wurk/railtie.rb +28 -0
- data/lib/wurk/redis_pool.rb +79 -0
- data/lib/wurk/retry_set.rb +17 -0
- data/lib/wurk/scheduled.rb +189 -0
- data/lib/wurk/scheduled_set.rb +18 -0
- data/lib/wurk/sorted_entry.rb +95 -0
- data/lib/wurk/stats.rb +190 -0
- data/lib/wurk/swarm/child_boot.rb +105 -0
- data/lib/wurk/swarm.rb +260 -0
- data/lib/wurk/testing.rb +102 -0
- data/lib/wurk/topology.rb +74 -0
- data/lib/wurk/unique.rb +240 -0
- data/lib/wurk/version.rb +5 -0
- data/lib/wurk/web/config.rb +180 -0
- data/lib/wurk/web/enterprise.rb +138 -0
- data/lib/wurk/web/search.rb +139 -0
- data/lib/wurk/web.rb +25 -0
- data/lib/wurk/work_set.rb +116 -0
- data/lib/wurk/worker/setter.rb +93 -0
- data/lib/wurk/worker.rb +216 -0
- data/lib/wurk.rb +238 -0
- data/vendor/assets/dashboard/assets/index-8P3N_m1X.js +152 -0
- data/vendor/assets/dashboard/assets/index-Bqz4_SOQ.css +1 -0
- data/vendor/assets/dashboard/index.html +13 -0
- data/vendor/assets/dashboard/wurk-manifest.json +4 -0
- metadata +232 -0
data/lib/wurk/cli.rb
ADDED
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'yaml'
|
|
4
|
+
require 'optparse'
|
|
5
|
+
require 'erb'
|
|
6
|
+
|
|
7
|
+
require_relative 'version'
|
|
8
|
+
require_relative 'configuration'
|
|
9
|
+
require_relative 'component'
|
|
10
|
+
require_relative 'capsule'
|
|
11
|
+
require_relative 'launcher'
|
|
12
|
+
|
|
13
|
+
module Wurk
|
|
14
|
+
# Standalone CLI. Loads from `exe/wurk` — never loads `wurk/rails` so the
|
|
15
|
+
# binary works without the Rails engine (the host app might not be Rails).
|
|
16
|
+
# Singleton because there is exactly one process-wide CLI; tests construct
|
|
17
|
+
# fresh `.new` instances to keep state isolated.
|
|
18
|
+
#
|
|
19
|
+
# Spec: docs/target/sidekiq-free.md §21 (Sidekiq::CLI).
|
|
20
|
+
class CLI # rubocop:disable Metrics/ClassLength
|
|
21
|
+
include Component
|
|
22
|
+
|
|
23
|
+
# Minimum Redis version Wurk supports — same as Sidekiq 8.x. The job JSON
|
|
24
|
+
# format and Lua scripts rely on commands introduced in Redis 7.
|
|
25
|
+
MIN_REDIS_VERSION = '7.0.0'
|
|
26
|
+
|
|
27
|
+
# Thread-backtrace dumper used by both TTIN and INFO. Same body — INFO is
|
|
28
|
+
# the modern name, TTIN is kept for parity with older Sidekiq users.
|
|
29
|
+
BACKTRACE_DUMPER = lambda do |cli|
|
|
30
|
+
Thread.list.each do |thread|
|
|
31
|
+
cli.logger.warn "Thread TID-#{(thread.object_id ^ ::Process.pid).to_s(36)} #{thread.name}"
|
|
32
|
+
if thread.backtrace
|
|
33
|
+
cli.logger.warn thread.backtrace.join("\n")
|
|
34
|
+
else
|
|
35
|
+
cli.logger.warn '<no backtrace available>'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
SIGNAL_HANDLERS = {
|
|
41
|
+
'INT' => ->(_cli) { raise Interrupt },
|
|
42
|
+
'TERM' => ->(_cli) { raise Interrupt },
|
|
43
|
+
'TSTP' => lambda do |cli|
|
|
44
|
+
cli.logger.info 'Received TSTP, no longer accepting new work'
|
|
45
|
+
cli.launcher.quiet
|
|
46
|
+
end,
|
|
47
|
+
'TTIN' => BACKTRACE_DUMPER,
|
|
48
|
+
'INFO' => BACKTRACE_DUMPER
|
|
49
|
+
}.freeze
|
|
50
|
+
|
|
51
|
+
# Table-driven so adding a flag doesn't grow `define_value_flags`'s ABC
|
|
52
|
+
# size and the surface matches the Sidekiq docs row-for-row. The 5th
|
|
53
|
+
# column is the assignment transform: `:to_i` parses as Integer, `:append`
|
|
54
|
+
# pushes onto a list (only `-q` uses that), nil = assign as-is.
|
|
55
|
+
OPTION_FLAGS = [
|
|
56
|
+
['-c', '--concurrency INT', :concurrency, 'processor threads to use', :to_i],
|
|
57
|
+
['-e', '--environment ENV', :environment, 'Application environment'],
|
|
58
|
+
['-g', '--tag TAG', :tag, 'Process tag for procline'],
|
|
59
|
+
['-q', '--queue QUEUE[,WEIGHT]', :queues, 'Queues to process with optional weights', :append],
|
|
60
|
+
['-r', '--require [PATH|DIR]', :require, 'Location of Rails app or .rb file to require'],
|
|
61
|
+
['-t', '--timeout NUM', :timeout, 'Shutdown timeout', :to_i],
|
|
62
|
+
['-v', '--verbose', :verbose, 'Print more verbose output'],
|
|
63
|
+
['-C', '--config PATH', :config_file, 'path to YAML config file']
|
|
64
|
+
].freeze
|
|
65
|
+
|
|
66
|
+
attr_accessor :launcher, :environment, :config
|
|
67
|
+
|
|
68
|
+
def self.instance
|
|
69
|
+
@instance ||= new
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Test seam: parallel suites can't share the singleton.
|
|
73
|
+
def self.reset_instance!
|
|
74
|
+
@instance = nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def initialize
|
|
78
|
+
@config = nil
|
|
79
|
+
@launcher = nil
|
|
80
|
+
@environment = nil
|
|
81
|
+
@parser = nil
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# `parse` is split from `run` so tests can drive option parsing without
|
|
85
|
+
# touching Redis or booting the host app.
|
|
86
|
+
def parse(args = ARGV.dup)
|
|
87
|
+
@config ||= Wurk.default_configuration
|
|
88
|
+
setup_options(args)
|
|
89
|
+
initialize_logger
|
|
90
|
+
validate!
|
|
91
|
+
self
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# `boot_app:` / `warmup:` are test seams. Production always passes true.
|
|
95
|
+
def run(boot_app: true, warmup: true)
|
|
96
|
+
boot_application if boot_app
|
|
97
|
+
self_read, self_write = ::IO.pipe
|
|
98
|
+
trap_signals(self_write)
|
|
99
|
+
validate_redis!
|
|
100
|
+
validate_pool_sizes!
|
|
101
|
+
@config[:identity] = identity
|
|
102
|
+
# Force lazy server-middleware chain so worker threads don't race
|
|
103
|
+
# against each other constructing it. Spec: Sidekiq::CLI line 104.
|
|
104
|
+
@config.server_middleware
|
|
105
|
+
::Process.warmup if warmup && ::Process.respond_to?(:warmup) && ENV['RUBY_DISABLE_WARMUP'] != '1'
|
|
106
|
+
fire_event(:startup, reverse: false, reraise: true)
|
|
107
|
+
launch(self_read)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def handle_signal(sig)
|
|
111
|
+
logger.debug { "Got #{sig} signal" }
|
|
112
|
+
handler = SIGNAL_HANDLERS[sig]
|
|
113
|
+
return logger.warn("No #{sig} signal handler registered, ignoring") unless handler
|
|
114
|
+
|
|
115
|
+
handler.call(self)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
private
|
|
119
|
+
|
|
120
|
+
# --- run helpers ----------------------------------------------------
|
|
121
|
+
|
|
122
|
+
def launch(self_read)
|
|
123
|
+
Wurk.server = true
|
|
124
|
+
@launcher = Wurk::Launcher.new(@config)
|
|
125
|
+
begin
|
|
126
|
+
@launcher.run
|
|
127
|
+
while self_read.wait_readable
|
|
128
|
+
signal = self_read.gets&.strip
|
|
129
|
+
break if signal.nil?
|
|
130
|
+
|
|
131
|
+
handle_signal(signal)
|
|
132
|
+
end
|
|
133
|
+
rescue Interrupt
|
|
134
|
+
logger.info 'Shutting down'
|
|
135
|
+
@launcher.stop
|
|
136
|
+
logger.info 'Bye!'
|
|
137
|
+
exit(0)
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
# Self-pipe signal pattern — handlers must be async-signal-safe, so we
|
|
142
|
+
# forward the signal name through a pipe and let the main thread loop
|
|
143
|
+
# over `self_read` in `launch`. Same approach as Sidekiq.
|
|
144
|
+
def trap_signals(self_write)
|
|
145
|
+
signal_names.each do |sig|
|
|
146
|
+
::Signal.trap(sig) { self_write.puts(sig) }
|
|
147
|
+
rescue ArgumentError
|
|
148
|
+
# JRuby and platforms without certain signals — log and move on.
|
|
149
|
+
warn("Signal #{sig} not supported")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def signal_names
|
|
154
|
+
%w[INT TERM TSTP TTIN INFO]
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def validate_redis!
|
|
158
|
+
info = redis_info
|
|
159
|
+
ver = ::Gem::Version.new(info['redis_version'])
|
|
160
|
+
if ver < ::Gem::Version.new(MIN_REDIS_VERSION)
|
|
161
|
+
raise "You are connected to Redis #{ver}, Wurk requires Redis #{MIN_REDIS_VERSION} or greater"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
maxmemory_policy = info['maxmemory_policy']
|
|
165
|
+
return if maxmemory_policy.nil? || maxmemory_policy.empty? || maxmemory_policy == 'noeviction'
|
|
166
|
+
|
|
167
|
+
logger.warn { <<~WARN }
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
WARNING: Your Redis instance will evict Wurk data under heavy load.
|
|
171
|
+
The 'noeviction' maxmemory policy is recommended (current policy: '#{maxmemory_policy}').
|
|
172
|
+
|
|
173
|
+
WARN
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def redis_info
|
|
177
|
+
@config.redis_pool.info
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def validate_pool_sizes!
|
|
181
|
+
@config.capsules.each_pair do |name, cap|
|
|
182
|
+
raise ArgumentError, "Pool size too small for #{name}" if cap.redis_pool.size < cap.concurrency
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# --- options + config-file --------------------------------------------
|
|
187
|
+
|
|
188
|
+
def setup_options(args)
|
|
189
|
+
opts = parse_options(args)
|
|
190
|
+
set_environment(opts[:environment])
|
|
191
|
+
opts[:config_file] ||= discover_config_file(opts[:require] || @config[:require])
|
|
192
|
+
opts = parse_config(opts[:config_file]).merge(opts) if opts[:config_file]
|
|
193
|
+
apply_defaults!(opts)
|
|
194
|
+
apply_options(opts)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def apply_defaults!(opts)
|
|
198
|
+
opts[:queues] ||= ['default']
|
|
199
|
+
return if opts[:concurrency] || ENV['RAILS_MAX_THREADS'].nil?
|
|
200
|
+
|
|
201
|
+
opts[:concurrency] = Integer(ENV.fetch('RAILS_MAX_THREADS'))
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def apply_options(opts)
|
|
205
|
+
@config.merge!(opts.except(:capsules))
|
|
206
|
+
cap = @config.default_capsule
|
|
207
|
+
cap.queues = opts[:queues]
|
|
208
|
+
cap.concurrency = opts[:concurrency] || @config[:concurrency]
|
|
209
|
+
apply_capsules(opts[:capsules])
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def apply_capsules(capsule_configs)
|
|
213
|
+
capsule_configs&.each do |name, cap_config|
|
|
214
|
+
@config.capsule(name.to_s) do |cap|
|
|
215
|
+
cap.queues = cap_config[:queues] if cap_config[:queues]
|
|
216
|
+
cap.concurrency = cap_config[:concurrency] if cap_config[:concurrency]
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def discover_config_file(require_path)
|
|
222
|
+
base = ::File.directory?(require_path.to_s) ? require_path.to_s : @config[:require].to_s
|
|
223
|
+
config_dir = ::File.join(base, 'config')
|
|
224
|
+
%w[wurk.yml wurk.yml.erb sidekiq.yml sidekiq.yml.erb].each do |name|
|
|
225
|
+
candidate = ::File.join(config_dir, name)
|
|
226
|
+
return candidate if ::File.exist?(candidate)
|
|
227
|
+
end
|
|
228
|
+
nil
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def parse_config(path)
|
|
232
|
+
raise ArgumentError, "No such file #{path}" unless ::File.exist?(path)
|
|
233
|
+
|
|
234
|
+
erb = ::ERB.new(::File.read(path), trim_mode: '-')
|
|
235
|
+
erb.filename = ::File.expand_path(path)
|
|
236
|
+
opts = ::YAML.safe_load(erb.result, permitted_classes: [Symbol], aliases: true) || {}
|
|
237
|
+
symbolize_keys_deep!(opts)
|
|
238
|
+
# Environment overlay: `production:` / `staging:` etc.
|
|
239
|
+
overlay = opts.delete(@environment.to_sym) if @environment
|
|
240
|
+
opts.merge!(overlay) if overlay.is_a?(Hash)
|
|
241
|
+
opts.delete(:strict) # Sidekiq parity — strict_fetch removed in 8.x
|
|
242
|
+
opts
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
def symbolize_keys_deep!(hash)
|
|
246
|
+
hash.keys.each do |k|
|
|
247
|
+
sym = k.respond_to?(:to_sym) ? k.to_sym : k
|
|
248
|
+
hash[sym] = hash.delete(k)
|
|
249
|
+
symbolize_keys_deep!(hash[sym]) if hash[sym].is_a?(Hash)
|
|
250
|
+
end
|
|
251
|
+
hash
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def set_environment(cli_env) # rubocop:disable Naming/AccessorMethodName
|
|
255
|
+
@environment = cli_env || ENV['APP_ENV'] || ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development'
|
|
256
|
+
@config[:environment] = @environment
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def parse_options(argv)
|
|
260
|
+
opts = {}
|
|
261
|
+
parser = option_parser(opts)
|
|
262
|
+
@parser = parser
|
|
263
|
+
parser.parse!(argv)
|
|
264
|
+
opts
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def option_parser(opts)
|
|
268
|
+
::OptionParser.new do |o|
|
|
269
|
+
o.banner = 'wurk [options]'
|
|
270
|
+
define_value_flags(o, opts)
|
|
271
|
+
define_meta_flags(o, opts)
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def define_value_flags(parser, opts)
|
|
276
|
+
OPTION_FLAGS.each do |short, long, key, desc, transform|
|
|
277
|
+
parser.on(short, long, desc) { |arg| assign_flag(opts, key, arg, transform) }
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def assign_flag(opts, key, arg, transform)
|
|
282
|
+
case transform
|
|
283
|
+
when :to_i then opts[key] = Integer(arg)
|
|
284
|
+
when :append then (opts[key] ||= []) << arg
|
|
285
|
+
else opts[key] = arg
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def define_meta_flags(parser, _opts)
|
|
290
|
+
parser.on('-V', '--version', 'Print version and exit') do
|
|
291
|
+
puts "Wurk #{Wurk::VERSION}"
|
|
292
|
+
exit(0)
|
|
293
|
+
end
|
|
294
|
+
parser.on_tail('-h', '--help', 'Show help') do
|
|
295
|
+
puts parser
|
|
296
|
+
exit(0)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
# --- application bootstrap --------------------------------------------
|
|
301
|
+
|
|
302
|
+
# Standalone mode must NOT load wurk/rails — even when pointed at a Rails
|
|
303
|
+
# app, that's the host's call to wire the railtie. The CLI only `require`s
|
|
304
|
+
# the host's entrypoint and reads the resulting classes.
|
|
305
|
+
def boot_application
|
|
306
|
+
ENV['RACK_ENV'] = ENV['RAILS_ENV'] = @environment
|
|
307
|
+
require_path = @config[:require]
|
|
308
|
+
if ::File.directory?(require_path.to_s)
|
|
309
|
+
boot_rails_application(require_path)
|
|
310
|
+
else
|
|
311
|
+
require ::File.expand_path(require_path)
|
|
312
|
+
@config[:tag] ||= default_tag
|
|
313
|
+
end
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def boot_rails_application(require_path)
|
|
317
|
+
require 'rails'
|
|
318
|
+
require ::File.expand_path("#{require_path}/config/environment.rb")
|
|
319
|
+
@config[:tag] ||= default_tag(::Rails.root) if defined?(::Rails) && ::Rails.respond_to?(:root)
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
def initialize_logger
|
|
323
|
+
return unless @config[:verbose] || ENV['DEBUG_INVOCATION'] == '1'
|
|
324
|
+
|
|
325
|
+
@config.logger.level = ::Logger::DEBUG
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
def validate!
|
|
329
|
+
require_path = @config[:require]
|
|
330
|
+
bad_path = !::File.exist?(require_path.to_s)
|
|
331
|
+
bad_rails = ::File.directory?(require_path.to_s) &&
|
|
332
|
+
!::File.exist?(::File.join(require_path, 'config/application.rb'))
|
|
333
|
+
return print_help_and_die if bad_path || bad_rails
|
|
334
|
+
|
|
335
|
+
%i[concurrency timeout].each do |opt|
|
|
336
|
+
raise ArgumentError, "#{opt}: #{@config[opt]} is not a valid value" if @config[opt].to_i <= 0
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
def print_help_and_die
|
|
341
|
+
logger.info '=================================================================='
|
|
342
|
+
logger.info ' Please point Wurk to a Rails application or a Ruby file'
|
|
343
|
+
logger.info ' to load your job classes with -r [DIR|FILE].'
|
|
344
|
+
logger.info '=================================================================='
|
|
345
|
+
logger.info @parser
|
|
346
|
+
exit(1)
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|