workhorse 0.3.9 → 0.4.0
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 +4 -4
- data/CHANGELOG.md +5 -1
- data/README.md +89 -1
- data/Rakefile +2 -1
- data/VERSION +1 -1
- data/lib/workhorse/db_job.rb +55 -10
- data/lib/workhorse/poller.rb +12 -2
- data/lib/workhorse/pool.rb +6 -0
- data/lib/workhorse/worker.rb +7 -1
- data/test/lib/test_helper.rb +8 -0
- data/test/workhorse/db_job_test.rb +58 -0
- data/test/workhorse/poller_test.rb +38 -0
- data/test/workhorse/pool_test.rb +22 -0
- data/test/workhorse/worker_test.rb +2 -2
- data/workhorse.gemspec +11 -8
- metadata +22 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 713d9c117c06a2e448ec9b963b216df9e46741f81f7e5e80c62f4b3648b1d29b
|
4
|
+
data.tar.gz: f625a84d3173812546d200feac847cbd16dcd800ee6d2f188e44302c79078211
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25818f59461494d50b08a00f863c81d48521998462643134454fac6b8ba7c6c7d2358213342373c01b4dbc5ef1dd4d02bdd561e1a1c9c5294d840095e1e5b931
|
7
|
+
data.tar.gz: 833e6132e223e85060253f678109dad5624802ad163c990caae78fc8a6de44820318505c36bb5709e2f7fd591f4ce7ed71aa2ed2487b6de43d3cec17eeb085da
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
# Workhorse
|
5
5
|
|
6
|
-
Multi-threaded job backend with database queuing for ruby.
|
6
|
+
Multi-threaded job backend with database queuing for ruby. Battle-tested and ready for production-use.
|
7
7
|
|
8
8
|
## Introduction
|
9
9
|
|
@@ -240,6 +240,23 @@ Workhorse::Daemon::ShellHandler.run count: 5 do
|
|
240
240
|
end
|
241
241
|
```
|
242
242
|
|
243
|
+
### Instant repolling
|
244
|
+
|
245
|
+
Per default, each worker only polls in the given interval. This means that if
|
246
|
+
you schedule, for example, 50 jobs at once and have a polling interval of 1
|
247
|
+
minute with a queue size of 1, the poller would tackle the first job and then
|
248
|
+
wait for a whole minute until the next poll. This would mean that these 50 jobs
|
249
|
+
would take at least 50 minutes to be executed, even if they only take a few
|
250
|
+
seconds each.
|
251
|
+
|
252
|
+
This is where *instant repolling* comes into play: Using the worker option
|
253
|
+
`instant_repolling`, you can force the poller to automatically re-poll the
|
254
|
+
database whenever a job has been performed. It then goes back to the usual
|
255
|
+
polling interval.
|
256
|
+
|
257
|
+
This setting is recommended for all setups and may eventually be enabled by
|
258
|
+
default.
|
259
|
+
|
243
260
|
## Exception handling
|
244
261
|
|
245
262
|
Per default, exceptions occurring in a worker thread will only be visible in the
|
@@ -257,6 +274,77 @@ Workhorse.setup do |config|
|
|
257
274
|
end
|
258
275
|
```
|
259
276
|
|
277
|
+
## Handling database jobs
|
278
|
+
|
279
|
+
Jobs stored in the database can be accessed via the ActiveRecord model
|
280
|
+
{Workhorse::DbJob}. This is the model representing a specific job database entry
|
281
|
+
and is not to be confused with the actual job class you're enqueueing.
|
282
|
+
|
283
|
+
### Obtaining database jobs
|
284
|
+
|
285
|
+
DbJobs are returned to you when enqueuing new jobs:
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
db_job = Workhorse.enqueue(MyJob.new)
|
289
|
+
```
|
290
|
+
|
291
|
+
You can also obtain a job via its ID that you either get from a returned job
|
292
|
+
(see example above) or else by manually querying the database table:
|
293
|
+
|
294
|
+
```ruby
|
295
|
+
db_job = Workhorse::DbJob.find(42)
|
296
|
+
```
|
297
|
+
|
298
|
+
Note that database job objects reflect the job at the point in time when the
|
299
|
+
database job object has been instantiated. To make sure you're looking at the
|
300
|
+
latest job info, use the in-place `reload` method:
|
301
|
+
|
302
|
+
```ruby
|
303
|
+
db_job.reload
|
304
|
+
```
|
305
|
+
|
306
|
+
You can also retrieve a list of jobs in a specific state using one of the
|
307
|
+
following methods:
|
308
|
+
|
309
|
+
```ruby
|
310
|
+
DbJob.waiting
|
311
|
+
DbJob.locked
|
312
|
+
DbJob.started
|
313
|
+
DbJob.succeeded
|
314
|
+
DbJob.failed
|
315
|
+
```
|
316
|
+
|
317
|
+
### Resetting jobs
|
318
|
+
|
319
|
+
Jobs in a state other than `waiting` are either being processed or else already
|
320
|
+
in a final state such as `succeeded` and won't be performed again. Workhorse
|
321
|
+
provides an API method for resetting jobs in the following cases:
|
322
|
+
|
323
|
+
* A job has succeeded or failed (states `succeeded` and `failed`) and needs to
|
324
|
+
re-run. In these cases, perform a non-forced reset:
|
325
|
+
|
326
|
+
```ruby
|
327
|
+
db_job.reset!
|
328
|
+
```
|
329
|
+
|
330
|
+
This is always safe to do, even with workers running.
|
331
|
+
|
332
|
+
* A job is stuck in state `locked` or `started` and the corresponding worker
|
333
|
+
(check the database field `locked_by`) is not running anymore, i.e. due to a
|
334
|
+
database connection loss or an unexpected worker crash. In these cases, the
|
335
|
+
job will never be processed, and, if the job is in a queue, the entire queue is
|
336
|
+
considered to be locked and no further jobs will be processed in this queue.
|
337
|
+
|
338
|
+
In these cases, make sure the worker is stopped and perform a forced reset:
|
339
|
+
|
340
|
+
```ruby
|
341
|
+
db_job.reset!(true)
|
342
|
+
```
|
343
|
+
|
344
|
+
Performing a reset will reset the job state to `waiting` and it will be
|
345
|
+
processed again. All meta fields will be reset as well. See inline documentation
|
346
|
+
of `Workhorse::DbJob#reset!` for more details.
|
347
|
+
|
260
348
|
## Frequently asked questions
|
261
349
|
|
262
350
|
Please consult the [FAQ](FAQ.md).
|
data/Rakefile
CHANGED
@@ -11,11 +11,12 @@ task :gemspec do
|
|
11
11
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
12
12
|
spec.require_paths = ['lib']
|
13
13
|
|
14
|
-
spec.add_development_dependency 'bundler'
|
14
|
+
spec.add_development_dependency 'bundler'
|
15
15
|
spec.add_development_dependency 'rake'
|
16
16
|
spec.add_development_dependency 'rubocop', '0.51.0'
|
17
17
|
spec.add_development_dependency 'minitest'
|
18
18
|
spec.add_development_dependency 'mysql2'
|
19
|
+
spec.add_development_dependency 'colorize'
|
19
20
|
spec.add_development_dependency 'benchmark-ips'
|
20
21
|
spec.add_dependency 'activesupport'
|
21
22
|
spec.add_dependency 'activerecord'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/lib/workhorse/db_job.rb
CHANGED
@@ -12,6 +12,58 @@ module Workhorse
|
|
12
12
|
|
13
13
|
self.table_name = 'jobs'
|
14
14
|
|
15
|
+
def self.waiting
|
16
|
+
where(state: STATE_WAITING)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.locked
|
20
|
+
where(state: STATE_LOCKED)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.started
|
24
|
+
where(state: STATE_STARTED)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.succeeded
|
28
|
+
where(state: STATE_SUCCEEDED)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.failed
|
32
|
+
where(state: STATE_FAILED)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Resets job to state "waiting" and clears all meta fields
|
36
|
+
# set by workhorse in course of processing this job.
|
37
|
+
#
|
38
|
+
# This is only allowed if the job is in a final state ("succeeded" or
|
39
|
+
# "failed"), as only those jobs are safe to modify; workhorse will not touch
|
40
|
+
# these jobs. To reset a job without checking the state it is in, set
|
41
|
+
# "force" to true. Prior to doing so, ensure that the job is not still being
|
42
|
+
# processed by a worker. If possible, shut down all workers before
|
43
|
+
# performing a forced reset.
|
44
|
+
#
|
45
|
+
# After the job is reset, it will be performed again. If you reset a job
|
46
|
+
# that has already been performed ("succeeded") or partially performed
|
47
|
+
# ("failed"), make sure the actions performed in the job are repeatable or
|
48
|
+
# have been rolled back. E.g. if the job already wrote something to an
|
49
|
+
# external API, it may cause inconsistencies if the job is performed again.
|
50
|
+
def reset!(force = false)
|
51
|
+
unless force
|
52
|
+
assert_state! STATE_SUCCEEDED, STATE_FAILED
|
53
|
+
end
|
54
|
+
|
55
|
+
self.state = STATE_WAITING
|
56
|
+
self.locked_at = nil
|
57
|
+
self.locked_by = nil
|
58
|
+
self.started_at = nil
|
59
|
+
self.succeeded_at = nil
|
60
|
+
self.failed_at = nil
|
61
|
+
self.last_error = nil
|
62
|
+
|
63
|
+
save!
|
64
|
+
end
|
65
|
+
|
66
|
+
# @private Only to be used by workhorse
|
15
67
|
def mark_locked!(worker_id)
|
16
68
|
if changed?
|
17
69
|
fail "Dirty jobs can't be locked."
|
@@ -27,6 +79,7 @@ module Workhorse
|
|
27
79
|
save!
|
28
80
|
end
|
29
81
|
|
82
|
+
# @private Only to be used by workhorse
|
30
83
|
def mark_started!
|
31
84
|
assert_state! STATE_LOCKED
|
32
85
|
|
@@ -35,6 +88,7 @@ module Workhorse
|
|
35
88
|
save!
|
36
89
|
end
|
37
90
|
|
91
|
+
# @private Only to be used by workhorse
|
38
92
|
def mark_failed!(exception)
|
39
93
|
assert_state! STATE_LOCKED, STATE_STARTED
|
40
94
|
|
@@ -44,6 +98,7 @@ module Workhorse
|
|
44
98
|
save!
|
45
99
|
end
|
46
100
|
|
101
|
+
# @private Only to be used by workhorse
|
47
102
|
def mark_succeeded!
|
48
103
|
assert_state! STATE_STARTED
|
49
104
|
|
@@ -57,15 +112,5 @@ module Workhorse
|
|
57
112
|
fail "Job #{id} is not in state #{states.inspect} but in state #{state.inspect}."
|
58
113
|
end
|
59
114
|
end
|
60
|
-
|
61
|
-
def assert_locked_by!(worker_id)
|
62
|
-
assert_state! STATE_WAITING
|
63
|
-
|
64
|
-
if locked_by.nil?
|
65
|
-
fail "Job #{id} is not locked by any worker."
|
66
|
-
elsif locked_by != worker_id
|
67
|
-
fail "Job #{id} is locked by another worker (#{locked_by})."
|
68
|
-
end
|
69
|
-
end
|
70
115
|
end
|
71
116
|
end
|
data/lib/workhorse/poller.rb
CHANGED
@@ -8,6 +8,7 @@ module Workhorse
|
|
8
8
|
@running = false
|
9
9
|
@table = Workhorse::DbJob.arel_table
|
10
10
|
@is_oracle = ActiveRecord::Base.connection.adapter_name == 'OracleEnhanced'
|
11
|
+
@instant_repoll = Concurrent::AtomicBoolean.new(false)
|
11
12
|
end
|
12
13
|
|
13
14
|
def running?
|
@@ -41,18 +42,27 @@ module Workhorse
|
|
41
42
|
@thread.join
|
42
43
|
end
|
43
44
|
|
45
|
+
# Call this to interrupt current sleep and perform the next poll as soon as
|
46
|
+
# possible, then resume in the normal polling interval.
|
47
|
+
def instant_repoll!
|
48
|
+
worker.log 'Aborting next sleep to perform instant repoll', :debug
|
49
|
+
@instant_repoll.make_true
|
50
|
+
end
|
51
|
+
|
44
52
|
private
|
45
53
|
|
46
54
|
def sleep
|
47
55
|
remaining = worker.polling_interval
|
48
56
|
|
49
|
-
while running? && remaining > 0
|
57
|
+
while running? && remaining > 0 && @instant_repoll.false?
|
50
58
|
Kernel.sleep 0.1
|
51
59
|
remaining -= 0.1
|
52
60
|
end
|
53
61
|
end
|
54
62
|
|
55
63
|
def poll
|
64
|
+
@instant_repoll.make_false
|
65
|
+
|
56
66
|
Workhorse.tx_callback.call do
|
57
67
|
# As we are the only thread posting into the worker pool, it is safe to
|
58
68
|
# get the number of idle threads without mutex synchronization. The
|
@@ -150,7 +160,7 @@ module Workhorse
|
|
150
160
|
|
151
161
|
select = select.lock
|
152
162
|
|
153
|
-
return Workhorse::DbJob.find_by_sql(select.to_sql)
|
163
|
+
return Workhorse::DbJob.find_by_sql(select.to_sql).to_a
|
154
164
|
end
|
155
165
|
|
156
166
|
# Returns a fresh Arel select manager containing the id of all waiting jobs,
|
data/lib/workhorse/pool.rb
CHANGED
@@ -14,6 +14,11 @@ module Workhorse
|
|
14
14
|
)
|
15
15
|
@mutex = Mutex.new
|
16
16
|
@active_threads = Concurrent::AtomicFixnum.new(0)
|
17
|
+
@on_idle = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def on_idle(&block)
|
21
|
+
@on_idle = block
|
17
22
|
end
|
18
23
|
|
19
24
|
# Posts a new work unit to the pool.
|
@@ -32,6 +37,7 @@ module Workhorse
|
|
32
37
|
yield
|
33
38
|
ensure
|
34
39
|
active_threads.decrement
|
40
|
+
@on_idle&.call
|
35
41
|
end
|
36
42
|
end
|
37
43
|
end
|
data/lib/workhorse/worker.rb
CHANGED
@@ -35,10 +35,12 @@ module Workhorse
|
|
35
35
|
# worker properly on INT and TERM signals.
|
36
36
|
# @param quiet [Boolean] If this is set to `false`, the worker will also log
|
37
37
|
# to STDOUT.
|
38
|
+
# @param instant_repolling [Boolean] If this is set to `true`, the worker
|
39
|
+
# immediately re-polls for new jobs when a job execution has finished.
|
38
40
|
# @param logger [Logger] An optional logger the worker will append to. This
|
39
41
|
# can be any instance of ruby's `Logger` but is commonly set to
|
40
42
|
# `Rails.logger`.
|
41
|
-
def initialize(queues: [], pool_size: nil, polling_interval: 300, auto_terminate: true, quiet: true, logger: nil)
|
43
|
+
def initialize(queues: [], pool_size: nil, polling_interval: 300, auto_terminate: true, quiet: true, instant_repolling: false, logger: nil)
|
42
44
|
@queues = queues
|
43
45
|
@pool_size = pool_size || queues.size + 1
|
44
46
|
@polling_interval = polling_interval
|
@@ -55,6 +57,10 @@ module Workhorse
|
|
55
57
|
fail 'Polling interval must be a multiple of 0.1.'
|
56
58
|
end
|
57
59
|
|
60
|
+
if instant_repolling
|
61
|
+
@pool.on_idle { @poller.instant_repoll! }
|
62
|
+
end
|
63
|
+
|
58
64
|
check_rails_env if defined?(Rails)
|
59
65
|
end
|
60
66
|
|
data/test/lib/test_helper.rb
CHANGED
@@ -11,6 +11,14 @@ class WorkhorseTest < ActiveSupport::TestCase
|
|
11
11
|
|
12
12
|
protected
|
13
13
|
|
14
|
+
def capture_log(level: :debug)
|
15
|
+
io = StringIO.new
|
16
|
+
logger = Logger.new(io, level: level)
|
17
|
+
yield logger
|
18
|
+
io.close
|
19
|
+
return io.string
|
20
|
+
end
|
21
|
+
|
14
22
|
def work(time = 2, options = {})
|
15
23
|
options[:pool_size] ||= 5
|
16
24
|
options[:polling_interval] ||= 1
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Workhorse::DbJobTest < WorkhorseTest
|
4
|
+
def test_reset_succeeded
|
5
|
+
job = Workhorse.enqueue(BasicJob.new(sleep_time: 0))
|
6
|
+
work 0.5
|
7
|
+
job.reload
|
8
|
+
assert_equal 'succeeded', job.state
|
9
|
+
|
10
|
+
job.reset!
|
11
|
+
|
12
|
+
assert_clean job
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_reset_failed
|
16
|
+
job = Workhorse.enqueue FailingTestJob
|
17
|
+
work 0.5
|
18
|
+
job.reload
|
19
|
+
assert_equal 'failed', job.state
|
20
|
+
|
21
|
+
job.reset!
|
22
|
+
|
23
|
+
assert_clean job
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_reset_locked_unforced
|
27
|
+
job = Workhorse.enqueue(BasicJob.new(sleep_time: 0))
|
28
|
+
job.mark_locked!(42)
|
29
|
+
|
30
|
+
err = assert_raises do
|
31
|
+
job.reset!
|
32
|
+
end
|
33
|
+
assert_equal %(Job #{job.id} is not in state [:succeeded, :failed] but in state "locked".), err.message
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_forced_reset
|
37
|
+
job = Workhorse.enqueue(BasicJob.new(sleep_time: 0))
|
38
|
+
job.mark_locked!(42)
|
39
|
+
|
40
|
+
assert_nothing_raised do
|
41
|
+
job.reset!(true)
|
42
|
+
end
|
43
|
+
|
44
|
+
assert_clean job
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def assert_clean(job)
|
50
|
+
assert_equal 'waiting', job.state
|
51
|
+
assert_nil job.locked_by
|
52
|
+
assert_nil job.locked_at
|
53
|
+
assert_nil job.started_at
|
54
|
+
assert_nil job.failed_at
|
55
|
+
assert_nil job.succeeded_at
|
56
|
+
assert_nil job.last_error
|
57
|
+
end
|
58
|
+
end
|
@@ -67,4 +67,42 @@ class Workhorse::PollerTest < WorkhorseTest
|
|
67
67
|
|
68
68
|
assert_equal [nil], w.poller.send(:valid_queues)
|
69
69
|
end
|
70
|
+
|
71
|
+
def test_with_instant_repolling
|
72
|
+
3.times do
|
73
|
+
Workhorse.enqueue BasicJob.new(sleep_time: 0)
|
74
|
+
end
|
75
|
+
|
76
|
+
assert_equal 3, Workhorse::DbJob.where(state: :waiting).count
|
77
|
+
|
78
|
+
log = capture_log do |logger|
|
79
|
+
work 2, instant_repolling: true, polling_interval: 5, pool_size: 1, logger: logger
|
80
|
+
end
|
81
|
+
|
82
|
+
assert_repolling_logged 3, log
|
83
|
+
assert_equal 3, Workhorse::DbJob.where(state: :succeeded).count
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_without_instant_repolling
|
87
|
+
3.times do
|
88
|
+
Workhorse.enqueue BasicJob.new(sleep_time: 0)
|
89
|
+
end
|
90
|
+
|
91
|
+
log = capture_log do |logger|
|
92
|
+
work 0.5, instant_repolling: false, polling_interval: 5, pool_size: 1, logger: logger
|
93
|
+
end
|
94
|
+
|
95
|
+
assert_repolling_logged 0, log
|
96
|
+
assert_equal 1, Workhorse::DbJob.where(state: :succeeded).count
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def setup
|
102
|
+
Workhorse::DbJob.delete_all
|
103
|
+
end
|
104
|
+
|
105
|
+
def assert_repolling_logged(count, log)
|
106
|
+
assert_equal count, log.scan(/Aborting next sleep to perform instant repoll/m).size
|
107
|
+
end
|
70
108
|
end
|
data/test/workhorse/pool_test.rb
CHANGED
@@ -19,6 +19,28 @@ class Workhorse::PoolTest < WorkhorseTest
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
def test_on_idle
|
23
|
+
on_idle_calls = Concurrent::AtomicFixnum.new
|
24
|
+
|
25
|
+
with_pool 2 do |p|
|
26
|
+
p.on_idle { on_idle_calls.increment }
|
27
|
+
|
28
|
+
assert_equal 0, on_idle_calls.value
|
29
|
+
|
30
|
+
p.post { sleep 0.2 }
|
31
|
+
p.post { sleep 0.4 }
|
32
|
+
|
33
|
+
sleep 0.1
|
34
|
+
assert_equal 0, on_idle_calls.value
|
35
|
+
|
36
|
+
sleep 0.2
|
37
|
+
assert_equal 1, on_idle_calls.value
|
38
|
+
|
39
|
+
sleep 0.1
|
40
|
+
assert_equal 2, on_idle_calls.value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
22
44
|
def test_overflow
|
23
45
|
with_pool 5 do |p|
|
24
46
|
5.times { p.post { sleep 0.2 } }
|
@@ -5,10 +5,10 @@ class Workhorse::WorkerTest < WorkhorseTest
|
|
5
5
|
with_worker(pool_size: 5, polling_interval: 0.2) do |w|
|
6
6
|
assert_equal 5, w.idle
|
7
7
|
|
8
|
-
sleep 0.
|
8
|
+
sleep 0.05
|
9
9
|
Workhorse.enqueue BasicJob.new(sleep_time: 0.2)
|
10
10
|
|
11
|
-
sleep 0.
|
11
|
+
sleep 0.25
|
12
12
|
assert_equal 4, w.idle
|
13
13
|
|
14
14
|
sleep 0.2
|
data/workhorse.gemspec
CHANGED
@@ -1,39 +1,41 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
# stub: workhorse 0.
|
2
|
+
# stub: workhorse 0.4.0 ruby lib
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "workhorse".freeze
|
6
|
-
s.version = "0.
|
6
|
+
s.version = "0.4.0"
|
7
7
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
9
|
s.require_paths = ["lib".freeze]
|
10
10
|
s.authors = ["Sitrox".freeze]
|
11
|
-
s.date = "2019-
|
12
|
-
s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.yml".freeze, "CHANGELOG.md".freeze, "FAQ.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/rubocop".freeze, "lib/generators/workhorse/install_generator.rb".freeze, "lib/generators/workhorse/templates/bin/workhorse.rb".freeze, "lib/generators/workhorse/templates/config/initializers/workhorse.rb".freeze, "lib/generators/workhorse/templates/create_table_jobs.rb".freeze, "lib/workhorse.rb".freeze, "lib/workhorse/daemon.rb".freeze, "lib/workhorse/daemon/shell_handler.rb".freeze, "lib/workhorse/db_job.rb".freeze, "lib/workhorse/enqueuer.rb".freeze, "lib/workhorse/jobs/cleanup_succeeded_jobs.rb".freeze, "lib/workhorse/jobs/run_rails_op.rb".freeze, "lib/workhorse/performer.rb".freeze, "lib/workhorse/poller.rb".freeze, "lib/workhorse/pool.rb".freeze, "lib/workhorse/worker.rb".freeze, "test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze, "workhorse.gemspec".freeze]
|
11
|
+
s.date = "2019-05-15"
|
12
|
+
s.files = [".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, ".travis.yml".freeze, "CHANGELOG.md".freeze, "FAQ.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/rubocop".freeze, "lib/generators/workhorse/install_generator.rb".freeze, "lib/generators/workhorse/templates/bin/workhorse.rb".freeze, "lib/generators/workhorse/templates/config/initializers/workhorse.rb".freeze, "lib/generators/workhorse/templates/create_table_jobs.rb".freeze, "lib/workhorse.rb".freeze, "lib/workhorse/daemon.rb".freeze, "lib/workhorse/daemon/shell_handler.rb".freeze, "lib/workhorse/db_job.rb".freeze, "lib/workhorse/enqueuer.rb".freeze, "lib/workhorse/jobs/cleanup_succeeded_jobs.rb".freeze, "lib/workhorse/jobs/run_rails_op.rb".freeze, "lib/workhorse/performer.rb".freeze, "lib/workhorse/poller.rb".freeze, "lib/workhorse/pool.rb".freeze, "lib/workhorse/worker.rb".freeze, "test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/db_job_test.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze, "workhorse.gemspec".freeze]
|
13
13
|
s.rubygems_version = "3.0.3".freeze
|
14
14
|
s.summary = "Multi-threaded job backend with database queuing for ruby.".freeze
|
15
|
-
s.test_files = ["test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze]
|
15
|
+
s.test_files = ["test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/db_job_test.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze]
|
16
16
|
|
17
17
|
if s.respond_to? :specification_version then
|
18
18
|
s.specification_version = 4
|
19
19
|
|
20
20
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
21
|
-
s.add_development_dependency(%q<bundler>.freeze, ["
|
21
|
+
s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
|
22
22
|
s.add_development_dependency(%q<rake>.freeze, [">= 0"])
|
23
23
|
s.add_development_dependency(%q<rubocop>.freeze, ["= 0.51.0"])
|
24
24
|
s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
|
25
25
|
s.add_development_dependency(%q<mysql2>.freeze, [">= 0"])
|
26
|
+
s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
|
26
27
|
s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
27
28
|
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 0"])
|
28
29
|
s.add_runtime_dependency(%q<activerecord>.freeze, [">= 0"])
|
29
30
|
s.add_runtime_dependency(%q<schemacop>.freeze, ["~> 2.0"])
|
30
31
|
s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
|
31
32
|
else
|
32
|
-
s.add_dependency(%q<bundler>.freeze, ["
|
33
|
+
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
33
34
|
s.add_dependency(%q<rake>.freeze, [">= 0"])
|
34
35
|
s.add_dependency(%q<rubocop>.freeze, ["= 0.51.0"])
|
35
36
|
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
36
37
|
s.add_dependency(%q<mysql2>.freeze, [">= 0"])
|
38
|
+
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
37
39
|
s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
38
40
|
s.add_dependency(%q<activesupport>.freeze, [">= 0"])
|
39
41
|
s.add_dependency(%q<activerecord>.freeze, [">= 0"])
|
@@ -41,11 +43,12 @@ Gem::Specification.new do |s|
|
|
41
43
|
s.add_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
|
42
44
|
end
|
43
45
|
else
|
44
|
-
s.add_dependency(%q<bundler>.freeze, ["
|
46
|
+
s.add_dependency(%q<bundler>.freeze, [">= 0"])
|
45
47
|
s.add_dependency(%q<rake>.freeze, [">= 0"])
|
46
48
|
s.add_dependency(%q<rubocop>.freeze, ["= 0.51.0"])
|
47
49
|
s.add_dependency(%q<minitest>.freeze, [">= 0"])
|
48
50
|
s.add_dependency(%q<mysql2>.freeze, [">= 0"])
|
51
|
+
s.add_dependency(%q<colorize>.freeze, [">= 0"])
|
49
52
|
s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
|
50
53
|
s.add_dependency(%q<activesupport>.freeze, [">= 0"])
|
51
54
|
s.add_dependency(%q<activerecord>.freeze, [">= 0"])
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: workhorse
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sitrox
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: colorize
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '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'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: benchmark-ips
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -187,6 +201,7 @@ files:
|
|
187
201
|
- test/lib/db_schema.rb
|
188
202
|
- test/lib/jobs.rb
|
189
203
|
- test/lib/test_helper.rb
|
204
|
+
- test/workhorse/db_job_test.rb
|
190
205
|
- test/workhorse/enqueuer_test.rb
|
191
206
|
- test/workhorse/performer_test.rb
|
192
207
|
- test/workhorse/poller_test.rb
|
@@ -219,6 +234,7 @@ test_files:
|
|
219
234
|
- test/lib/db_schema.rb
|
220
235
|
- test/lib/jobs.rb
|
221
236
|
- test/lib/test_helper.rb
|
237
|
+
- test/workhorse/db_job_test.rb
|
222
238
|
- test/workhorse/enqueuer_test.rb
|
223
239
|
- test/workhorse/performer_test.rb
|
224
240
|
- test/workhorse/poller_test.rb
|