inst-jobs 3.0.8 → 3.1.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/db/migrate/20200330230722_add_id_to_get_delayed_jobs_index.rb +4 -2
- data/db/migrate/20200825011002_add_strand_order_override.rb +2 -1
- data/db/migrate/20210809145804_add_n_strand_index.rb +2 -1
- data/db/migrate/20220328152900_add_failed_jobs_indicies.rb +12 -0
- data/db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb +7 -0
- data/lib/delayed/backend/active_record.rb +77 -7
- data/lib/delayed/backend/base.rb +28 -10
- data/lib/delayed/batch.rb +1 -1
- data/lib/delayed/cli.rb +3 -2
- data/lib/delayed/lifecycle.rb +9 -2
- data/lib/delayed/log_tailer.rb +2 -2
- data/lib/delayed/message_sending.rb +9 -6
- data/lib/delayed/performable_method.rb +22 -16
- data/lib/delayed/periodic.rb +2 -2
- data/lib/delayed/pool.rb +12 -2
- data/lib/delayed/server.rb +8 -2
- data/lib/delayed/settings.rb +5 -1
- data/lib/delayed/version.rb +1 -1
- data/lib/delayed/work_queue/parent_process/server.rb +7 -3
- data/lib/delayed/worker/health_check.rb +1 -1
- data/lib/delayed/worker/process_helper.rb +4 -4
- data/lib/delayed/worker.rb +22 -11
- metadata +18 -119
- data/spec/active_record_job_spec.rb +0 -294
- data/spec/delayed/cli_spec.rb +0 -25
- data/spec/delayed/daemon_spec.rb +0 -38
- data/spec/delayed/message_sending_spec.rb +0 -108
- data/spec/delayed/periodic_spec.rb +0 -32
- data/spec/delayed/server_spec.rb +0 -103
- data/spec/delayed/settings_spec.rb +0 -48
- data/spec/delayed/work_queue/in_process_spec.rb +0 -31
- data/spec/delayed/work_queue/parent_process/client_spec.rb +0 -87
- data/spec/delayed/work_queue/parent_process/server_spec.rb +0 -280
- data/spec/delayed/work_queue/parent_process_spec.rb +0 -60
- data/spec/delayed/worker/consul_health_check_spec.rb +0 -63
- data/spec/delayed/worker/health_check_spec.rb +0 -134
- data/spec/delayed/worker_spec.rb +0 -105
- data/spec/migrate/20140924140513_add_story_table.rb +0 -9
- data/spec/sample_jobs.rb +0 -79
- data/spec/shared/delayed_batch.rb +0 -105
- data/spec/shared/delayed_method.rb +0 -287
- data/spec/shared/performable_method.rb +0 -75
- data/spec/shared/shared_backend.rb +0 -1221
- data/spec/shared/testing.rb +0 -50
- data/spec/shared/worker.rb +0 -413
- data/spec/shared_jobs_specs.rb +0 -17
- data/spec/spec_helper.rb +0 -136
@@ -163,7 +163,7 @@ module Delayed
|
|
163
163
|
forced_latency: forced_latency
|
164
164
|
)
|
165
165
|
logger.debug(
|
166
|
-
"Fetched and locked #{response.values.flatten.size} new jobs for workers (#{response.keys.join(
|
166
|
+
"Fetched and locked #{response.values.flatten.size} new jobs for workers (#{response.keys.join(", ")})."
|
167
167
|
)
|
168
168
|
response.each do |(worker_name, locked_jobs)|
|
169
169
|
if worker_name == prefetch_owner
|
@@ -226,7 +226,11 @@ module Delayed
|
|
226
226
|
|
227
227
|
# otherwise just reconnect and let it retry
|
228
228
|
logger.warn("failed to unlock prefetched jobs - connection terminated; skipping for now")
|
229
|
-
|
229
|
+
if Rails.version < "6.1"
|
230
|
+
::Delayed::Job.clear_all_connections!
|
231
|
+
else
|
232
|
+
::Delayed::Job.clear_all_connections!(nil)
|
233
|
+
end
|
230
234
|
end
|
231
235
|
end
|
232
236
|
|
@@ -263,7 +267,7 @@ module Delayed
|
|
263
267
|
end
|
264
268
|
|
265
269
|
def prefetch_owner
|
266
|
-
"prefetch:#{Socket.gethostname rescue
|
270
|
+
"prefetch:#{Socket.gethostname rescue "X"}"
|
267
271
|
end
|
268
272
|
|
269
273
|
def parent_exited?
|
@@ -34,7 +34,7 @@ module Delayed
|
|
34
34
|
# no other worker is trying to do this right now (and if we abandon the
|
35
35
|
# operation, the transaction will end, releasing the advisory lock).
|
36
36
|
result = Delayed::Job.attempt_advisory_lock("Delayed::Worker::HealthCheck#reschedule_abandoned_jobs")
|
37
|
-
|
37
|
+
next unless result
|
38
38
|
|
39
39
|
horizon = 5.minutes.ago
|
40
40
|
|
@@ -9,9 +9,9 @@ module Delayed
|
|
9
9
|
ALIVE_CHECK_LINUX = '[ -d "/proc/$WORKER_PID" ]'
|
10
10
|
ALIVE_CHECK_MAC = "ps -p $WORKER_PID > /dev/null"
|
11
11
|
ALIVE_CHECK = RUBY_PLATFORM.include?("darwin") ? ALIVE_CHECK_MAC : ALIVE_CHECK_LINUX
|
12
|
-
SCRIPT_TEMPLATE =
|
13
|
-
WORKER_PID="
|
14
|
-
ORIGINAL_MTIME="
|
12
|
+
SCRIPT_TEMPLATE = <<~SH
|
13
|
+
WORKER_PID="%{pid}" # an example, filled from ruby when the check is created
|
14
|
+
ORIGINAL_MTIME="%{mtime}" # an example, filled from ruby when the check is created
|
15
15
|
|
16
16
|
if #{ALIVE_CHECK}; then
|
17
17
|
CURRENT_MTIME=$(#{STAT})
|
@@ -26,7 +26,7 @@ module Delayed
|
|
26
26
|
else
|
27
27
|
exit 255 # The process is no more, trigger a "critical" state.
|
28
28
|
fi
|
29
|
-
|
29
|
+
SH
|
30
30
|
|
31
31
|
def self.mtime(pid)
|
32
32
|
if RUBY_PLATFORM.include?("darwin")
|
data/lib/delayed/worker.rb
CHANGED
@@ -64,6 +64,7 @@ module Delayed
|
|
64
64
|
@max_priority = options[:max_priority]
|
65
65
|
@max_job_count = options[:worker_max_job_count].to_i
|
66
66
|
@max_memory_usage = options[:worker_max_memory_usage].to_i
|
67
|
+
@memory_high_water = options[:worker_memory_high_water]&.to_i || (@max_memory_usage / 2)
|
67
68
|
@work_queue = options.delete(:work_queue) || WorkQueue::InProcess.new
|
68
69
|
@health_check_type = Settings.worker_health_check_type
|
69
70
|
@health_check_config = Settings.worker_health_check_config
|
@@ -77,7 +78,7 @@ module Delayed
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def name
|
80
|
-
@name ||= "#{Socket.gethostname rescue
|
81
|
+
@name ||= "#{Socket.gethostname rescue "X"}:#{id}"
|
81
82
|
end
|
82
83
|
|
83
84
|
def process_name=(new_name)
|
@@ -99,8 +100,13 @@ module Delayed
|
|
99
100
|
|
100
101
|
def start
|
101
102
|
logger.info "Starting worker"
|
103
|
+
begin
|
104
|
+
Process.setrlimit(:DATA, @max_memory_usage, @max_memory_usage * 2) if @max_memory_usage.positive?
|
105
|
+
rescue Errno::EINVAL
|
106
|
+
# couldn't set an OS-level limit
|
107
|
+
end
|
102
108
|
self.process_name =
|
103
|
-
"start:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority ||
|
109
|
+
"start:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
|
104
110
|
@self_pipe = IO.pipe
|
105
111
|
work_queue.init
|
106
112
|
|
@@ -170,7 +176,7 @@ module Delayed
|
|
170
176
|
|
171
177
|
self.class.lifecycle.run_callbacks(:loop, self) do
|
172
178
|
self.process_name =
|
173
|
-
"pop:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority ||
|
179
|
+
"pop:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
|
174
180
|
job = self.class.lifecycle.run_callbacks(:pop, self) do
|
175
181
|
work_queue.get_and_lock_next_available(name, config)
|
176
182
|
end
|
@@ -184,10 +190,10 @@ module Delayed
|
|
184
190
|
@exit = true
|
185
191
|
end
|
186
192
|
|
187
|
-
if @
|
193
|
+
if @memory_high_water.positive?
|
188
194
|
memory = sample_memory
|
189
|
-
if memory > @
|
190
|
-
logger.debug "Memory usage of #{memory} exceeds
|
195
|
+
if memory > @memory_high_water
|
196
|
+
logger.debug "Memory usage of #{memory} exceeds high water of #{@memory_high_water}, dying"
|
191
197
|
@exit = true
|
192
198
|
else
|
193
199
|
logger.debug "Memory usage: #{memory}"
|
@@ -196,7 +202,7 @@ module Delayed
|
|
196
202
|
end
|
197
203
|
else
|
198
204
|
self.process_name =
|
199
|
-
"wait:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority ||
|
205
|
+
"wait:#{Settings.worker_procname_prefix}#{@queue_name}:#{min_priority || 0}:#{max_priority || "max"}"
|
200
206
|
sleep(Settings.sleep_delay + (rand * Settings.sleep_delay_stagger)) unless exit?
|
201
207
|
end
|
202
208
|
end
|
@@ -220,7 +226,7 @@ module Delayed
|
|
220
226
|
end
|
221
227
|
job.destroy
|
222
228
|
end
|
223
|
-
logger.info("Completed #{log_job(job)} #{format(
|
229
|
+
logger.info("Completed #{log_job(job, :short)} #{format("%.0fms", (runtime * 1000))}")
|
224
230
|
end
|
225
231
|
rescue ::Delayed::RetriableError => e
|
226
232
|
can_retry = job.attempts + 1 < job.inferred_max_attempts
|
@@ -233,6 +239,11 @@ module Delayed
|
|
233
239
|
# still reschedule the job though.
|
234
240
|
job.reschedule(e)
|
235
241
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
242
|
+
if e.is_a?(NoMemoryError)
|
243
|
+
GC.start # try and free up some memory before reporting the error
|
244
|
+
logger.debug "Could not allocate memory (max is #{@max_memory_usage}), dying"
|
245
|
+
@exit = true
|
246
|
+
end
|
236
247
|
self.class.lifecycle.run_callbacks(:error, self, job, e) do
|
237
248
|
handle_failed_job(job, e)
|
238
249
|
end
|
@@ -269,17 +280,17 @@ module Delayed
|
|
269
280
|
when :long
|
270
281
|
"#{job.full_name} #{Settings.job_detailed_log_format.call(job)}"
|
271
282
|
else
|
272
|
-
job.full_name
|
283
|
+
"#{job.full_name} #{Settings.job_short_log_format.call(job)}".strip
|
273
284
|
end
|
274
285
|
end
|
275
286
|
|
276
287
|
# set up the session context information, so that it gets logged with the job log lines
|
277
288
|
# also set up a unique tmpdir, which will get removed at the end of the job.
|
278
289
|
def configure_for_job(job)
|
279
|
-
previous_tmpdir = ENV
|
290
|
+
previous_tmpdir = ENV.fetch("TMPDIR", nil)
|
280
291
|
|
281
292
|
self.class.running_job(job) do
|
282
|
-
dir = Dir.mktmpdir("job-#{job.id}-#{name.gsub(/[^\w.]/,
|
293
|
+
dir = Dir.mktmpdir("job-#{job.id}-#{name.gsub(/[^\w.]/, ".")}-")
|
283
294
|
begin
|
284
295
|
ENV["TMPDIR"] = dir
|
285
296
|
yield
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inst-jobs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.1.14
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cody Cutrer
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-11-22 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -116,20 +116,6 @@ dependencies:
|
|
116
116
|
- - ">="
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '6.0'
|
119
|
-
- !ruby/object:Gem::Dependency
|
120
|
-
name: appraisal
|
121
|
-
requirement: !ruby/object:Gem::Requirement
|
122
|
-
requirements:
|
123
|
-
- - "~>"
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: '2.4'
|
126
|
-
type: :development
|
127
|
-
prerelease: false
|
128
|
-
version_requirements: !ruby/object:Gem::Requirement
|
129
|
-
requirements:
|
130
|
-
- - "~>"
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
version: '2.4'
|
133
119
|
- !ruby/object:Gem::Dependency
|
134
120
|
name: bump
|
135
121
|
requirement: !ruby/object:Gem::Requirement
|
@@ -192,14 +178,14 @@ dependencies:
|
|
192
178
|
requirements:
|
193
179
|
- - "~>"
|
194
180
|
- !ruby/object:Gem::Version
|
195
|
-
version: 2.
|
181
|
+
version: 2.6.3
|
196
182
|
type: :development
|
197
183
|
prerelease: false
|
198
184
|
version_requirements: !ruby/object:Gem::Requirement
|
199
185
|
requirements:
|
200
186
|
- - "~>"
|
201
187
|
- !ruby/object:Gem::Version
|
202
|
-
version: 2.
|
188
|
+
version: 2.6.3
|
203
189
|
- !ruby/object:Gem::Dependency
|
204
190
|
name: pg
|
205
191
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,20 +228,6 @@ dependencies:
|
|
242
228
|
- - ">="
|
243
229
|
- !ruby/object:Gem::Version
|
244
230
|
version: '0'
|
245
|
-
- !ruby/object:Gem::Dependency
|
246
|
-
name: rails
|
247
|
-
requirement: !ruby/object:Gem::Requirement
|
248
|
-
requirements:
|
249
|
-
- - ">="
|
250
|
-
- !ruby/object:Gem::Version
|
251
|
-
version: '0'
|
252
|
-
type: :development
|
253
|
-
prerelease: false
|
254
|
-
version_requirements: !ruby/object:Gem::Requirement
|
255
|
-
requirements:
|
256
|
-
- - ">="
|
257
|
-
- !ruby/object:Gem::Version
|
258
|
-
version: '0'
|
259
231
|
- !ruby/object:Gem::Dependency
|
260
232
|
name: rake
|
261
233
|
requirement: !ruby/object:Gem::Requirement
|
@@ -285,33 +257,19 @@ dependencies:
|
|
285
257
|
- !ruby/object:Gem::Version
|
286
258
|
version: '3.10'
|
287
259
|
- !ruby/object:Gem::Dependency
|
288
|
-
name: rubocop
|
260
|
+
name: rubocop-inst
|
289
261
|
requirement: !ruby/object:Gem::Requirement
|
290
262
|
requirements:
|
291
263
|
- - "~>"
|
292
264
|
- !ruby/object:Gem::Version
|
293
|
-
version: '1
|
265
|
+
version: '1'
|
294
266
|
type: :development
|
295
267
|
prerelease: false
|
296
268
|
version_requirements: !ruby/object:Gem::Requirement
|
297
269
|
requirements:
|
298
270
|
- - "~>"
|
299
271
|
- !ruby/object:Gem::Version
|
300
|
-
version: '1
|
301
|
-
- !ruby/object:Gem::Dependency
|
302
|
-
name: rubocop-performance
|
303
|
-
requirement: !ruby/object:Gem::Requirement
|
304
|
-
requirements:
|
305
|
-
- - "~>"
|
306
|
-
- !ruby/object:Gem::Version
|
307
|
-
version: 1.12.0
|
308
|
-
type: :development
|
309
|
-
prerelease: false
|
310
|
-
version_requirements: !ruby/object:Gem::Requirement
|
311
|
-
requirements:
|
312
|
-
- - "~>"
|
313
|
-
- !ruby/object:Gem::Version
|
314
|
-
version: 1.12.0
|
272
|
+
version: '1'
|
315
273
|
- !ruby/object:Gem::Dependency
|
316
274
|
name: rubocop-rails
|
317
275
|
requirement: !ruby/object:Gem::Requirement
|
@@ -386,16 +344,16 @@ dependencies:
|
|
386
344
|
name: timecop
|
387
345
|
requirement: !ruby/object:Gem::Requirement
|
388
346
|
requirements:
|
389
|
-
- -
|
347
|
+
- - "~>"
|
390
348
|
- !ruby/object:Gem::Version
|
391
|
-
version: 0.9
|
349
|
+
version: '0.9'
|
392
350
|
type: :development
|
393
351
|
prerelease: false
|
394
352
|
version_requirements: !ruby/object:Gem::Requirement
|
395
353
|
requirements:
|
396
|
-
- -
|
354
|
+
- - "~>"
|
397
355
|
- !ruby/object:Gem::Version
|
398
|
-
version: 0.9
|
356
|
+
version: '0.9'
|
399
357
|
- !ruby/object:Gem::Dependency
|
400
358
|
name: webmock
|
401
359
|
requirement: !ruby/object:Gem::Requirement
|
@@ -410,20 +368,6 @@ dependencies:
|
|
410
368
|
- - ">="
|
411
369
|
- !ruby/object:Gem::Version
|
412
370
|
version: '0'
|
413
|
-
- !ruby/object:Gem::Dependency
|
414
|
-
name: wwtd
|
415
|
-
requirement: !ruby/object:Gem::Requirement
|
416
|
-
requirements:
|
417
|
-
- - "~>"
|
418
|
-
- !ruby/object:Gem::Version
|
419
|
-
version: 1.4.0
|
420
|
-
type: :development
|
421
|
-
prerelease: false
|
422
|
-
version_requirements: !ruby/object:Gem::Requirement
|
423
|
-
requirements:
|
424
|
-
- - "~>"
|
425
|
-
- !ruby/object:Gem::Version
|
426
|
-
version: 1.4.0
|
427
371
|
description:
|
428
372
|
email:
|
429
373
|
- cody@instructure.com
|
@@ -473,6 +417,8 @@ files:
|
|
473
417
|
- db/migrate/20220128084800_update_insert_trigger_for_singleton_unique_constraint_change.rb
|
474
418
|
- db/migrate/20220128084900_update_delete_trigger_for_singleton_unique_constraint_change.rb
|
475
419
|
- db/migrate/20220203063200_remove_old_singleton_index.rb
|
420
|
+
- db/migrate/20220328152900_add_failed_jobs_indicies.rb
|
421
|
+
- db/migrate/20220519204546_add_requeued_job_id_to_failed_jobs.rb
|
476
422
|
- exe/inst_jobs
|
477
423
|
- lib/delayed/backend/active_record.rb
|
478
424
|
- lib/delayed/backend/base.rb
|
@@ -512,33 +458,10 @@ files:
|
|
512
458
|
- lib/delayed/yaml_extensions.rb
|
513
459
|
- lib/delayed_job.rb
|
514
460
|
- lib/inst-jobs.rb
|
515
|
-
- spec/active_record_job_spec.rb
|
516
|
-
- spec/delayed/cli_spec.rb
|
517
|
-
- spec/delayed/daemon_spec.rb
|
518
|
-
- spec/delayed/message_sending_spec.rb
|
519
|
-
- spec/delayed/periodic_spec.rb
|
520
|
-
- spec/delayed/server_spec.rb
|
521
|
-
- spec/delayed/settings_spec.rb
|
522
|
-
- spec/delayed/work_queue/in_process_spec.rb
|
523
|
-
- spec/delayed/work_queue/parent_process/client_spec.rb
|
524
|
-
- spec/delayed/work_queue/parent_process/server_spec.rb
|
525
|
-
- spec/delayed/work_queue/parent_process_spec.rb
|
526
|
-
- spec/delayed/worker/consul_health_check_spec.rb
|
527
|
-
- spec/delayed/worker/health_check_spec.rb
|
528
|
-
- spec/delayed/worker_spec.rb
|
529
|
-
- spec/migrate/20140924140513_add_story_table.rb
|
530
|
-
- spec/sample_jobs.rb
|
531
|
-
- spec/shared/delayed_batch.rb
|
532
|
-
- spec/shared/delayed_method.rb
|
533
|
-
- spec/shared/performable_method.rb
|
534
|
-
- spec/shared/shared_backend.rb
|
535
|
-
- spec/shared/testing.rb
|
536
|
-
- spec/shared/worker.rb
|
537
|
-
- spec/shared_jobs_specs.rb
|
538
|
-
- spec/spec_helper.rb
|
539
461
|
homepage: https://github.com/instructure/inst-jobs
|
540
462
|
licenses: []
|
541
|
-
metadata:
|
463
|
+
metadata:
|
464
|
+
rubygems_mfa_required: 'true'
|
542
465
|
post_install_message:
|
543
466
|
rdoc_options: []
|
544
467
|
require_paths:
|
@@ -547,39 +470,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
547
470
|
requirements:
|
548
471
|
- - ">="
|
549
472
|
- !ruby/object:Gem::Version
|
550
|
-
version: '2.
|
473
|
+
version: '2.7'
|
551
474
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
552
475
|
requirements:
|
553
476
|
- - ">="
|
554
477
|
- !ruby/object:Gem::Version
|
555
478
|
version: '0'
|
556
479
|
requirements: []
|
557
|
-
rubygems_version: 3.1.
|
480
|
+
rubygems_version: 3.1.6
|
558
481
|
signing_key:
|
559
482
|
specification_version: 4
|
560
483
|
summary: Instructure-maintained fork of delayed_job
|
561
|
-
test_files:
|
562
|
-
- spec/active_record_job_spec.rb
|
563
|
-
- spec/delayed/cli_spec.rb
|
564
|
-
- spec/delayed/daemon_spec.rb
|
565
|
-
- spec/delayed/message_sending_spec.rb
|
566
|
-
- spec/delayed/periodic_spec.rb
|
567
|
-
- spec/delayed/server_spec.rb
|
568
|
-
- spec/delayed/settings_spec.rb
|
569
|
-
- spec/delayed/work_queue/in_process_spec.rb
|
570
|
-
- spec/delayed/work_queue/parent_process/client_spec.rb
|
571
|
-
- spec/delayed/work_queue/parent_process/server_spec.rb
|
572
|
-
- spec/delayed/work_queue/parent_process_spec.rb
|
573
|
-
- spec/delayed/worker/consul_health_check_spec.rb
|
574
|
-
- spec/delayed/worker/health_check_spec.rb
|
575
|
-
- spec/delayed/worker_spec.rb
|
576
|
-
- spec/migrate/20140924140513_add_story_table.rb
|
577
|
-
- spec/sample_jobs.rb
|
578
|
-
- spec/shared/delayed_batch.rb
|
579
|
-
- spec/shared/delayed_method.rb
|
580
|
-
- spec/shared/performable_method.rb
|
581
|
-
- spec/shared/shared_backend.rb
|
582
|
-
- spec/shared/testing.rb
|
583
|
-
- spec/shared/worker.rb
|
584
|
-
- spec/shared_jobs_specs.rb
|
585
|
-
- spec/spec_helper.rb
|
484
|
+
test_files: []
|