asynchronic 1.6.3 → 3.0.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 +5 -5
- data/.travis.yml +6 -11
- data/README.md +0 -1
- data/asynchronic.gemspec +4 -10
- data/lib/asynchronic.rb +8 -2
- data/lib/asynchronic/data_store/lazy_value.rb +1 -1
- data/lib/asynchronic/data_store/redis.rb +10 -10
- data/lib/asynchronic/environment.rb +3 -3
- data/lib/asynchronic/garbage_collector.rb +2 -0
- data/lib/asynchronic/notifier/broadcaster.rb +30 -0
- data/lib/asynchronic/notifier/in_memory.rb +33 -0
- data/lib/asynchronic/process.rb +32 -10
- data/lib/asynchronic/queue_engine/in_memory.rb +5 -0
- data/lib/asynchronic/queue_engine/ost.rb +30 -16
- data/lib/asynchronic/queue_engine/synchronic.rb +5 -0
- data/lib/asynchronic/version.rb +2 -2
- data/lib/asynchronic/worker.rb +1 -1
- data/spec/data_store/data_store_examples.rb +10 -10
- data/spec/data_store/lazy_value_examples.rb +0 -1
- data/spec/expectations.rb +6 -1
- data/spec/facade_spec.rb +12 -0
- data/spec/jobs.rb +2 -2
- data/spec/minitest_helper.rb +2 -0
- data/spec/process/life_cycle_examples.rb +100 -64
- data/spec/process/life_cycle_in_memory_spec.rb +1 -0
- data/spec/process/life_cycle_redis_spec.rb +1 -0
- data/spec/queue_engine/ost_spec.rb +4 -0
- data/spec/queue_engine/queue_engine_examples.rb +13 -7
- data/spec/queue_engine/synchronic_spec.rb +5 -1
- data/spec/worker/in_memory_spec.rb +1 -0
- data/spec/worker/redis_spec.rb +1 -0
- data/spec/worker/worker_examples.rb +1 -1
- metadata +27 -26
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 17e77f96cb1792507a8d82d9745bbf766c484cf4308bf41e268f33b28fb7671c
|
4
|
+
data.tar.gz: 33e566a52873e57adb7f79db2cfc179a269bf990ac57d9c0db3ebe698800c42d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fac5b943ac35aa8d40ea3ec3bf73f3a827ecc6e040814c958a5a17f5d44a3bed544aa8956db5e7679b32cb9f2ccde5a859f20e3e0f150e85fe5d52fec6936dee
|
7
|
+
data.tar.gz: 70750e88c0c4a3ac3647c1d98bccd9e70447c92c226a11829175153c2bcf401e77ee07aff82b702cf8aee8db4c6961b0bf7e467304060592a176be0c29d3755c
|
data/.travis.yml
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
language: ruby
|
2
2
|
|
3
3
|
rvm:
|
4
|
-
- 1.9.3
|
5
4
|
- 2.0
|
6
5
|
- 2.1
|
7
6
|
- 2.2
|
8
|
-
- 2.3
|
9
|
-
- 2.4
|
10
|
-
- 2.5
|
11
|
-
- 2.6
|
12
|
-
-
|
13
|
-
- jruby-9.
|
7
|
+
- 2.3
|
8
|
+
- 2.4
|
9
|
+
- 2.5
|
10
|
+
- 2.6
|
11
|
+
- 2.7
|
12
|
+
- jruby-9.2.9.0
|
14
13
|
- ruby-head
|
15
14
|
- jruby-head
|
16
15
|
|
@@ -20,9 +19,5 @@ matrix:
|
|
20
19
|
- rvm: ruby-head
|
21
20
|
- rvm: jruby-head
|
22
21
|
|
23
|
-
before_install:
|
24
|
-
- rvm all-gemsets do gem uninstall bundler -ax || true
|
25
|
-
- gem install bundler -v "< 2"
|
26
|
-
|
27
22
|
services:
|
28
23
|
- redis-server
|
data/README.md
CHANGED
@@ -4,7 +4,6 @@
|
|
4
4
|
[](https://travis-ci.org/gabynaiman/asynchronic)
|
5
5
|
[](https://coveralls.io/r/gabynaiman/asynchronic?branch=master)
|
6
6
|
[](https://codeclimate.com/github/gabynaiman/asynchronic)
|
7
|
-
[](https://gemnasium.com/gabynaiman/asynchronic)
|
8
7
|
|
9
8
|
DSL for asynchronic pipeline using queues over Redis
|
10
9
|
|
data/asynchronic.gemspec
CHANGED
@@ -18,25 +18,19 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency '
|
22
|
-
spec.add_dependency '
|
21
|
+
spec.add_dependency 'ost', '~> 1.0'
|
22
|
+
spec.add_dependency 'broadcaster', '~> 1.0'
|
23
23
|
spec.add_dependency 'class_config', '~> 0.0'
|
24
24
|
spec.add_dependency 'transparent_proxy', '~> 0.0'
|
25
25
|
spec.add_dependency 'multi_require', '~> 1.0'
|
26
26
|
|
27
|
-
spec.add_development_dependency '
|
28
|
-
spec.add_development_dependency 'rake', '~> 11.0'
|
27
|
+
spec.add_development_dependency 'rake', '~> 12.0'
|
29
28
|
spec.add_development_dependency 'minitest', '~> 5.0', '< 5.11'
|
30
29
|
spec.add_development_dependency 'minitest-great_expectations', '~> 0.0'
|
30
|
+
spec.add_development_dependency 'minitest-stub_any_instance', '~> 1.0'
|
31
31
|
spec.add_development_dependency 'minitest-colorin', '~> 0.1'
|
32
32
|
spec.add_development_dependency 'minitest-line', '~> 0.6'
|
33
33
|
spec.add_development_dependency 'simplecov', '~> 0.12'
|
34
34
|
spec.add_development_dependency 'coveralls', '~> 0.8'
|
35
35
|
spec.add_development_dependency 'pry-nav', '~> 0.2'
|
36
|
-
|
37
|
-
if RUBY_VERSION < '2'
|
38
|
-
spec.add_development_dependency 'term-ansicolor', '~> 1.3.0'
|
39
|
-
spec.add_development_dependency 'tins', '~> 1.6.0'
|
40
|
-
spec.add_development_dependency 'json', '~> 1.8'
|
41
|
-
end
|
42
36
|
end
|
data/lib/asynchronic.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'securerandom'
|
3
|
-
require 'redis'
|
4
3
|
require 'ost'
|
4
|
+
require 'redic'
|
5
|
+
require 'broadcaster'
|
5
6
|
require 'class_config'
|
6
7
|
require 'transparent_proxy'
|
7
8
|
require 'logger'
|
8
9
|
require 'multi_require'
|
10
|
+
require 'timeout'
|
11
|
+
require 'socket'
|
9
12
|
|
10
13
|
MultiRequire.require_relative_pattern 'asynchronic/**/*.rb'
|
11
14
|
|
@@ -16,13 +19,16 @@ module Asynchronic
|
|
16
19
|
attr_config :default_queue, :asynchronic
|
17
20
|
attr_config :queue_engine, QueueEngine::InMemory.new
|
18
21
|
attr_config :data_store, DataStore::InMemory.new
|
22
|
+
attr_config :notifier, Notifier::InMemory.new
|
19
23
|
attr_config :logger, Logger.new($stdout)
|
20
24
|
attr_config :retry_timeout, 30
|
21
25
|
attr_config :garbage_collector_timeout, 30
|
22
26
|
attr_config :redis_data_store_sync_timeout, 0.01
|
27
|
+
attr_config :keep_alive_timeout, 1
|
28
|
+
attr_config :connection_name, "HOST=#{Socket.gethostname},PID=#{::Process.pid},UUID=#{SecureRandom.uuid}"
|
23
29
|
|
24
30
|
def self.environment
|
25
|
-
Environment.new queue_engine, data_store
|
31
|
+
Environment.new queue_engine, data_store, notifier
|
26
32
|
end
|
27
33
|
|
28
34
|
def self.[](pid)
|
@@ -8,11 +8,11 @@ module Asynchronic
|
|
8
8
|
|
9
9
|
def initialize(scope, *args)
|
10
10
|
@scope = Key[scope]
|
11
|
-
@
|
11
|
+
@redis = Redic.new(*args)
|
12
12
|
end
|
13
13
|
|
14
14
|
def [](key)
|
15
|
-
value = @
|
15
|
+
value = @redis.call! 'GET', @scope[key]
|
16
16
|
value ? Marshal.load(value) : nil
|
17
17
|
rescue => ex
|
18
18
|
Asynchronic.logger.warn('Asynchronic') { ex.message }
|
@@ -20,33 +20,33 @@ module Asynchronic
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def []=(key, value)
|
23
|
-
@
|
23
|
+
@redis.call! 'SET', @scope[key], Marshal.dump(value)
|
24
24
|
end
|
25
25
|
|
26
26
|
def delete(key)
|
27
|
-
@
|
27
|
+
@redis.call! 'DEL', @scope[key]
|
28
28
|
end
|
29
29
|
|
30
30
|
def delete_cascade(key)
|
31
|
-
@
|
32
|
-
@
|
31
|
+
@redis.call! 'DEL', @scope[key]
|
32
|
+
@redis.call!('KEYS', @scope[key]['*']).each { |k| @redis.call! 'DEL', k }
|
33
33
|
end
|
34
34
|
|
35
35
|
def keys
|
36
|
-
@
|
36
|
+
@redis.call!('KEYS', @scope['*']).map { |k| Key[k].remove_first }
|
37
37
|
end
|
38
38
|
|
39
39
|
def synchronize(key)
|
40
|
-
while @
|
40
|
+
while @redis.call!('GETSET', @scope[key][LOCKED], LOCKED) == LOCKED
|
41
41
|
sleep Asynchronic.redis_data_store_sync_timeout
|
42
42
|
end
|
43
43
|
yield
|
44
44
|
ensure
|
45
|
-
@
|
45
|
+
@redis.call! 'DEL', @scope[key][LOCKED]
|
46
46
|
end
|
47
47
|
|
48
48
|
def connection_args
|
49
|
-
[@scope, @
|
49
|
+
[@scope, @redis.url]
|
50
50
|
end
|
51
51
|
|
52
52
|
def self.connect(*args)
|
@@ -1,12 +1,12 @@
|
|
1
1
|
module Asynchronic
|
2
2
|
class Environment
|
3
3
|
|
4
|
-
attr_reader :queue_engine
|
5
|
-
attr_reader :data_store
|
4
|
+
attr_reader :queue_engine, :data_store, :notifier
|
6
5
|
|
7
|
-
def initialize(queue_engine, data_store)
|
6
|
+
def initialize(queue_engine, data_store, notifier)
|
8
7
|
@queue_engine = queue_engine
|
9
8
|
@data_store = data_store
|
9
|
+
@notifier = notifier
|
10
10
|
end
|
11
11
|
|
12
12
|
def queue(name)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Asynchronic
|
2
|
+
module Notifier
|
3
|
+
class Broadcaster
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
options[:logger] ||= Asynchronic.logger
|
7
|
+
@broadcaster = ::Broadcaster.new options
|
8
|
+
end
|
9
|
+
|
10
|
+
def publish(pid, event, data=nil)
|
11
|
+
@broadcaster.publish DataStore::Key[pid][event], data
|
12
|
+
end
|
13
|
+
|
14
|
+
def subscribe(pid, event, &block)
|
15
|
+
@broadcaster.subscribe DataStore::Key[pid][event] do |data|
|
16
|
+
block.call data
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def unsubscribe(subscription_id)
|
21
|
+
@broadcaster.unsubscribe subscription_id
|
22
|
+
end
|
23
|
+
|
24
|
+
def unsubscribe_all
|
25
|
+
@broadcaster.unsubscribe_all
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Asynchronic
|
2
|
+
module Notifier
|
3
|
+
class InMemory
|
4
|
+
|
5
|
+
def publish(pid, event, data=nil)
|
6
|
+
subscriptions[DataStore::Key[pid][event]].each_value do |block|
|
7
|
+
block.call data
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def subscribe(pid, event, &block)
|
12
|
+
SecureRandom.uuid.tap do |subscription_id|
|
13
|
+
subscriptions[DataStore::Key[pid][event]][subscription_id] = block
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def unsubscribe(subscription_id)
|
18
|
+
subscriptions.each_value { |s| s.delete subscription_id }
|
19
|
+
end
|
20
|
+
|
21
|
+
def unsubscribe_all
|
22
|
+
subscriptions.clear
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def subscriptions
|
28
|
+
@subscriptions ||= Hash.new { |h,k| h[k] = {} }
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/asynchronic/process.rb
CHANGED
@@ -11,9 +11,11 @@ module Asynchronic
|
|
11
11
|
aborted: :finalized_at
|
12
12
|
}
|
13
13
|
|
14
|
-
ATTRIBUTE_NAMES = [:type, :name, :queue, :status, :dependencies, :data, :result, :error] | TIME_TRACKING_MAP.values.uniq
|
14
|
+
ATTRIBUTE_NAMES = [:type, :name, :queue, :status, :dependencies, :data, :result, :error, :connection_name] | TIME_TRACKING_MAP.values.uniq
|
15
15
|
|
16
|
+
AUTOMATIC_ABORTED_ERROR_MESSAGE = 'Automatic aborted before execution'
|
16
17
|
CANCELED_ERROR_MESSAGE = 'Canceled'
|
18
|
+
DEAD_ERROR_MESSAGE = 'Process connection broken'
|
17
19
|
|
18
20
|
attr_reader :id
|
19
21
|
|
@@ -47,6 +49,14 @@ module Asynchronic
|
|
47
49
|
abort! CANCELED_ERROR_MESSAGE
|
48
50
|
end
|
49
51
|
|
52
|
+
def dead?
|
53
|
+
(running? && !connected?) || processes.any?(&:dead?)
|
54
|
+
end
|
55
|
+
|
56
|
+
def abort_if_dead
|
57
|
+
abort! DEAD_ERROR_MESSAGE if dead?
|
58
|
+
end
|
59
|
+
|
50
60
|
def destroy
|
51
61
|
data_store.delete_cascade
|
52
62
|
end
|
@@ -75,7 +85,7 @@ module Asynchronic
|
|
75
85
|
|
76
86
|
def processes
|
77
87
|
data_store.scoped(:processes).keys.
|
78
|
-
select { |k| k.sections.count == 2 && k.match(
|
88
|
+
select { |k| k.sections.count == 2 && k.match(/\|name$/) }.
|
79
89
|
sort.map { |k| Process.new environment, id[:processes][k.remove_last] }
|
80
90
|
end
|
81
91
|
|
@@ -88,13 +98,11 @@ module Asynchronic
|
|
88
98
|
end
|
89
99
|
|
90
100
|
def real_error
|
91
|
-
return nil
|
101
|
+
return nil if !aborted?
|
92
102
|
|
93
|
-
processes.
|
94
|
-
return child.real_error if child.error
|
95
|
-
end
|
103
|
+
first_aborted_child = processes.select(&:aborted?).sort_by(&:finalized_at).first
|
96
104
|
|
97
|
-
error.message
|
105
|
+
first_aborted_child ? first_aborted_child.real_error : error.message
|
98
106
|
end
|
99
107
|
|
100
108
|
def dependencies
|
@@ -186,8 +194,12 @@ module Asynchronic
|
|
186
194
|
|
187
195
|
def status=(status)
|
188
196
|
Asynchronic.logger.info('Asynchronic') { "#{status.to_s.capitalize} #{type} (#{id})" }
|
197
|
+
|
189
198
|
data_store[:status] = status
|
190
199
|
data_store[TIME_TRACKING_MAP[status]] = Time.now if TIME_TRACKING_MAP.key? status
|
200
|
+
|
201
|
+
environment.notifier.publish id, :status_changed, status
|
202
|
+
environment.notifier.publish id, :finalized if finalized?
|
191
203
|
end
|
192
204
|
|
193
205
|
STATUSES.each do |status|
|
@@ -202,19 +214,22 @@ module Asynchronic
|
|
202
214
|
end
|
203
215
|
end
|
204
216
|
|
205
|
-
def abort!(exception
|
206
|
-
self.error = Error.new exception
|
217
|
+
def abort!(exception)
|
218
|
+
self.error = Error.new exception
|
207
219
|
aborted!
|
208
220
|
end
|
209
221
|
|
210
222
|
def run
|
223
|
+
self.connection_name = Asynchronic.connection_name
|
224
|
+
|
211
225
|
if root.aborted?
|
212
|
-
abort!
|
226
|
+
abort! AUTOMATIC_ABORTED_ERROR_MESSAGE
|
213
227
|
else
|
214
228
|
running!
|
215
229
|
self.result = job.call
|
216
230
|
waiting!
|
217
231
|
end
|
232
|
+
|
218
233
|
rescue Exception => ex
|
219
234
|
message = "Failed process #{type} (#{id})\n#{ex.class} #{ex.message}\n#{ex.backtrace.join("\n")}"
|
220
235
|
Asynchronic.logger.error('Asynchronic') { message }
|
@@ -249,5 +264,12 @@ module Asynchronic
|
|
249
264
|
parent.queue if parent
|
250
265
|
end
|
251
266
|
|
267
|
+
def connected?
|
268
|
+
connection_name && environment.queue_engine.active_connections.include?(connection_name)
|
269
|
+
rescue => ex
|
270
|
+
Asynchronic.logger.error('Asynchronic') { "#{ex.message}\n#{ex.backtrace.join("\n")}" }
|
271
|
+
true
|
272
|
+
end
|
273
|
+
|
252
274
|
end
|
253
275
|
end
|
@@ -1,17 +1,14 @@
|
|
1
1
|
module Asynchronic
|
2
2
|
module QueueEngine
|
3
3
|
class Ost
|
4
|
-
|
5
|
-
attr_reader :default_queue
|
6
4
|
|
7
|
-
|
8
|
-
::Ost.connect options[:redis] if options.key?(:redis)
|
9
|
-
@default_queue = options[:default_queue]
|
10
|
-
@queues ||= Hash.new { |h,k| h[k] = Queue.new k }
|
11
|
-
end
|
5
|
+
attr_reader :redis, :default_queue
|
12
6
|
|
13
|
-
def
|
14
|
-
@
|
7
|
+
def initialize(options={})
|
8
|
+
@redis = Redic.new(*Array(options[:redis]))
|
9
|
+
@default_queue = options.fetch(:default_queue, Asynchronic.default_queue)
|
10
|
+
@queues ||= Hash.new { |h,k| h[k] = Queue.new k, redis }
|
11
|
+
@keep_alive_thread = notify_keep_alive
|
15
12
|
end
|
16
13
|
|
17
14
|
def [](name)
|
@@ -19,12 +16,12 @@ module Asynchronic
|
|
19
16
|
end
|
20
17
|
|
21
18
|
def queues
|
22
|
-
(@queues.values.map(&:key) | redis.
|
19
|
+
(@queues.values.map(&:key) | redis.call!('KEYS', 'ost:*')).map { |q| q.to_s[4..-1].to_sym }
|
23
20
|
end
|
24
21
|
|
25
22
|
def clear
|
26
23
|
@queues.clear
|
27
|
-
redis.
|
24
|
+
redis.call!('KEYS', 'ost:*').each { |k| redis.call!('DEL', k) }
|
28
25
|
end
|
29
26
|
|
30
27
|
def listener
|
@@ -35,21 +32,38 @@ module Asynchronic
|
|
35
32
|
true
|
36
33
|
end
|
37
34
|
|
35
|
+
def active_connections
|
36
|
+
redis.call!('CLIENT', 'LIST').split("\n").map do |connection_info|
|
37
|
+
name_attr = connection_info.split(' ').detect { |a| a.match(/name=/) }
|
38
|
+
name_attr ? name_attr[5..-1] : nil
|
39
|
+
end.uniq.compact.reject(&:empty?)
|
40
|
+
end
|
41
|
+
|
38
42
|
private
|
39
43
|
|
40
|
-
def
|
41
|
-
|
44
|
+
def notify_keep_alive
|
45
|
+
Thread.new do
|
46
|
+
loop do
|
47
|
+
redis.call! 'CLIENT', 'SETNAME', Asynchronic.connection_name
|
48
|
+
sleep Asynchronic.keep_alive_timeout
|
49
|
+
end
|
50
|
+
end
|
42
51
|
end
|
43
52
|
|
44
53
|
|
45
54
|
class Queue < ::Ost::Queue
|
46
55
|
|
56
|
+
def initialize(name, redis)
|
57
|
+
super name
|
58
|
+
self.redis = redis
|
59
|
+
end
|
60
|
+
|
47
61
|
def pop
|
48
|
-
key
|
62
|
+
redis.call! 'RPOP', key
|
49
63
|
end
|
50
64
|
|
51
65
|
def empty?
|
52
|
-
|
66
|
+
redis.call!('EXISTS', key) == 0
|
53
67
|
end
|
54
68
|
|
55
69
|
def size
|
@@ -68,7 +82,7 @@ module Asynchronic
|
|
68
82
|
def listen(queue, &block)
|
69
83
|
@current_queue = queue
|
70
84
|
Asynchronic.retry_execution(self.class, 'listen') do
|
71
|
-
queue.each
|
85
|
+
queue.each(&block)
|
72
86
|
end
|
73
87
|
end
|
74
88
|
|
data/lib/asynchronic/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module Asynchronic
|
2
|
-
VERSION = '
|
3
|
-
end
|
2
|
+
VERSION = '3.0.2'
|
3
|
+
end
|
data/lib/asynchronic/worker.rb
CHANGED
@@ -23,7 +23,7 @@ class Asynchronic::Worker
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def stop
|
26
|
-
Asynchronic.logger.info('Asynchronic') { "Stopping worker of #{
|
26
|
+
Asynchronic.logger.info('Asynchronic') { "Stopping worker of #{queue_name} (#{Process.pid})" }
|
27
27
|
listener.stop
|
28
28
|
end
|
29
29
|
|
@@ -22,19 +22,19 @@ module DataStoreExamples
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'Delete cascade' do
|
25
|
-
data_store[Key[:key_1]] = 1
|
26
|
-
data_store[Key[:key_1][:key_1_1]] = 2
|
27
|
-
data_store[Key[:key_1][:key_1_2]] = 3
|
28
|
-
data_store[Key[:key_2]] = 4
|
29
|
-
data_store[Key[:key_2][:key_2_1]] = 5
|
30
|
-
data_store[Key[:key_2][:key_2_2]] = 6
|
25
|
+
data_store[Asynchronic::DataStore::Key[:key_1]] = 1
|
26
|
+
data_store[Asynchronic::DataStore::Key[:key_1][:key_1_1]] = 2
|
27
|
+
data_store[Asynchronic::DataStore::Key[:key_1][:key_1_2]] = 3
|
28
|
+
data_store[Asynchronic::DataStore::Key[:key_2]] = 4
|
29
|
+
data_store[Asynchronic::DataStore::Key[:key_2][:key_2_1]] = 5
|
30
|
+
data_store[Asynchronic::DataStore::Key[:key_2][:key_2_2]] = 6
|
31
31
|
|
32
|
-
data_store.delete_cascade Key[:key_1]
|
32
|
+
data_store.delete_cascade Asynchronic::DataStore::Key[:key_1]
|
33
33
|
|
34
34
|
data_store.keys.sort.must_equal [
|
35
|
-
Key[:key_2],
|
36
|
-
Key[:key_2][:key_2_1],
|
37
|
-
Key[:key_2][:key_2_2]
|
35
|
+
Asynchronic::DataStore::Key[:key_2],
|
36
|
+
Asynchronic::DataStore::Key[:key_2][:key_2_1],
|
37
|
+
Asynchronic::DataStore::Key[:key_2][:key_2_2]
|
38
38
|
]
|
39
39
|
end
|
40
40
|
|
data/spec/expectations.rb
CHANGED
@@ -75,6 +75,10 @@ module MiniTest::Assertions
|
|
75
75
|
process.finalized_at.must_be_instance_of Time
|
76
76
|
end
|
77
77
|
|
78
|
+
def assert_have_connection_name(process)
|
79
|
+
process.connection_name.must_equal Asynchronic.connection_name
|
80
|
+
end
|
81
|
+
|
78
82
|
end
|
79
83
|
|
80
84
|
Asynchronic::QueueEngine::InMemory::Queue.infect_an_assertion :assert_enqueued, :must_enqueued
|
@@ -85,4 +89,5 @@ Asynchronic::Process.infect_an_assertion :assert_be_pending, :must_be_pending, :
|
|
85
89
|
Asynchronic::Process.infect_an_assertion :assert_be_queued, :must_be_queued, :unary
|
86
90
|
Asynchronic::Process.infect_an_assertion :assert_be_waiting, :must_be_waiting, :unary
|
87
91
|
Asynchronic::Process.infect_an_assertion :assert_be_completed, :must_be_completed, :unary
|
88
|
-
Asynchronic::Process.infect_an_assertion :assert_be_aborted, :must_be_aborted, :unary
|
92
|
+
Asynchronic::Process.infect_an_assertion :assert_be_aborted, :must_be_aborted, :unary
|
93
|
+
Asynchronic::Process.infect_an_assertion :assert_have_connection_name, :must_have_connection_name, :unary
|
data/spec/facade_spec.rb
CHANGED
@@ -64,4 +64,16 @@ describe Asynchronic, 'Facade' do
|
|
64
64
|
Asynchronic.garbage_collector.must_be_instance_of Asynchronic::GarbageCollector
|
65
65
|
end
|
66
66
|
|
67
|
+
it 'Redis data store sync timeout' do
|
68
|
+
Asynchronic.redis_data_store_sync_timeout.must_equal 0.01
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'Keep alive timeout' do
|
72
|
+
Asynchronic.keep_alive_timeout.must_equal 1
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'Connection name' do
|
76
|
+
Asynchronic.connection_name.must_match /^HOST=#{Socket.gethostname},PID=#{::Process.pid}/
|
77
|
+
end
|
78
|
+
|
67
79
|
end
|
data/spec/jobs.rb
CHANGED
@@ -200,7 +200,7 @@ end
|
|
200
200
|
class WithRetriesJob < Asynchronic::Job
|
201
201
|
def call
|
202
202
|
@counter = 0
|
203
|
-
retry_when [RuntimeError] do
|
203
|
+
retry_when [RuntimeError], 0.1 do
|
204
204
|
@counter += 1
|
205
205
|
raise 'Counter < 3' if @counter < 3
|
206
206
|
@counter
|
@@ -326,7 +326,7 @@ class NestedJobWithErrorInChildJob < Asynchronic::Job
|
|
326
326
|
end
|
327
327
|
|
328
328
|
|
329
|
-
class
|
329
|
+
class AbortQueuedAfterErrorJob < Asynchronic::Job
|
330
330
|
def call
|
331
331
|
async Child_1
|
332
332
|
async Child_2
|
data/spec/minitest_helper.rb
CHANGED
@@ -1,26 +1,68 @@
|
|
1
1
|
module LifeCycleExamples
|
2
2
|
|
3
|
-
let(:env) { Asynchronic::Environment.new queue_engine, data_store }
|
3
|
+
let(:env) { Asynchronic::Environment.new queue_engine, data_store, notifier }
|
4
4
|
|
5
5
|
let(:queue) { env.default_queue }
|
6
6
|
|
7
7
|
after do
|
8
8
|
data_store.clear
|
9
9
|
queue_engine.clear
|
10
|
+
notifier.unsubscribe_all
|
10
11
|
end
|
11
12
|
|
12
13
|
def create(type, params={})
|
13
|
-
env.create_process
|
14
|
+
env.create_process(type, params).tap do |process|
|
15
|
+
process.must_be_initialized
|
16
|
+
end
|
14
17
|
end
|
15
18
|
|
16
19
|
def execute(queue)
|
17
|
-
env.load_process(queue.pop)
|
20
|
+
process = env.load_process(queue.pop)
|
21
|
+
|
22
|
+
events = []
|
23
|
+
status_changed_id = notifier.subscribe(process.id, :status_changed) { |status| events << status }
|
24
|
+
|
25
|
+
is_finalized = false
|
26
|
+
finalized_id = notifier.subscribe(process.id, :finalized) { is_finalized = true }
|
27
|
+
|
28
|
+
process.execute
|
29
|
+
|
30
|
+
process.must_have_connection_name
|
31
|
+
process.wont_be :dead?
|
32
|
+
|
33
|
+
process.send(:connected?).must_be_true
|
34
|
+
|
35
|
+
env.queue_engine.stub(:active_connections, ->() { raise 'Forced error' }) do
|
36
|
+
process.send(:connected?).must_be_true
|
37
|
+
end
|
38
|
+
|
39
|
+
with_retries do
|
40
|
+
events.last.must_equal process.status
|
41
|
+
process.finalized?.must_equal is_finalized
|
42
|
+
end
|
43
|
+
|
44
|
+
notifier.unsubscribe status_changed_id
|
45
|
+
notifier.unsubscribe finalized_id
|
46
|
+
|
47
|
+
status = process.status
|
48
|
+
process.abort_if_dead
|
49
|
+
process.status.must_equal status
|
50
|
+
end
|
51
|
+
|
52
|
+
def with_retries(&block)
|
53
|
+
Timeout.timeout(3) do
|
54
|
+
begin
|
55
|
+
block.call
|
56
|
+
rescue Minitest::Assertion
|
57
|
+
sleep 0.001
|
58
|
+
retry
|
59
|
+
end
|
60
|
+
end
|
18
61
|
end
|
19
62
|
|
20
63
|
it 'Basic' do
|
21
64
|
process = create BasicJob, input: 1
|
22
65
|
|
23
|
-
process.must_be_initialized
|
24
66
|
process.must_have_params input: 1
|
25
67
|
queue.must_be_empty
|
26
68
|
|
@@ -39,7 +81,6 @@ module LifeCycleExamples
|
|
39
81
|
it 'Sequential' do
|
40
82
|
process = create SequentialJob, input: 50
|
41
83
|
|
42
|
-
process.must_be_initialized
|
43
84
|
process.must_have_params input: 50
|
44
85
|
queue.must_be_empty
|
45
86
|
|
@@ -77,7 +118,6 @@ module LifeCycleExamples
|
|
77
118
|
it 'Graph' do
|
78
119
|
process = create GraphJob, input: 100
|
79
120
|
|
80
|
-
process.must_be_initialized
|
81
121
|
process.must_have_params input: 100
|
82
122
|
queue.must_be_empty
|
83
123
|
|
@@ -133,7 +173,6 @@ module LifeCycleExamples
|
|
133
173
|
it 'Parallel' do
|
134
174
|
process = create ParallelJob, input: 10, times: 3
|
135
175
|
|
136
|
-
process.must_be_initialized
|
137
176
|
process.must_have_params input: 10, times: 3
|
138
177
|
queue.must_be_empty
|
139
178
|
|
@@ -167,7 +206,6 @@ module LifeCycleExamples
|
|
167
206
|
it 'Nested' do
|
168
207
|
process = create NestedJob, input: 4
|
169
208
|
|
170
|
-
process.must_be_initialized
|
171
209
|
process.must_have_params input: 4
|
172
210
|
queue.must_be_empty
|
173
211
|
|
@@ -207,7 +245,6 @@ module LifeCycleExamples
|
|
207
245
|
it 'Alias' do
|
208
246
|
process = create AliasJob
|
209
247
|
|
210
|
-
process.must_be_initialized
|
211
248
|
queue.must_be_empty
|
212
249
|
|
213
250
|
process.enqueue
|
@@ -261,7 +298,6 @@ module LifeCycleExamples
|
|
261
298
|
it 'Custom queue' do
|
262
299
|
process = create CustomQueueJob, input: 'hello'
|
263
300
|
|
264
|
-
process.must_be_initialized
|
265
301
|
process.must_have_params input: 'hello'
|
266
302
|
|
267
303
|
env.queue(:queue_1).must_be_empty
|
@@ -302,7 +338,6 @@ module LifeCycleExamples
|
|
302
338
|
it 'Exception' do
|
303
339
|
process = create ExceptionJob
|
304
340
|
|
305
|
-
process.must_be_initialized
|
306
341
|
queue.must_be_empty
|
307
342
|
|
308
343
|
process.enqueue
|
@@ -320,7 +355,6 @@ module LifeCycleExamples
|
|
320
355
|
it 'Inner exception' do
|
321
356
|
process = create InnerExceptionJob
|
322
357
|
|
323
|
-
process.must_be_initialized
|
324
358
|
queue.must_be_empty
|
325
359
|
|
326
360
|
process.enqueue
|
@@ -348,7 +382,6 @@ module LifeCycleExamples
|
|
348
382
|
it 'Forward reference' do
|
349
383
|
process = create ForwardReferenceJob
|
350
384
|
|
351
|
-
process.must_be_initialized
|
352
385
|
queue.must_be_empty
|
353
386
|
|
354
387
|
process.enqueue
|
@@ -391,7 +424,6 @@ module LifeCycleExamples
|
|
391
424
|
it 'Job with retries' do
|
392
425
|
process = create WithRetriesJob
|
393
426
|
|
394
|
-
process.must_be_initialized
|
395
427
|
queue.must_be_empty
|
396
428
|
|
397
429
|
process.enqueue
|
@@ -486,80 +518,81 @@ module LifeCycleExamples
|
|
486
518
|
process.real_error.must_equal "Error in parent"
|
487
519
|
end
|
488
520
|
|
489
|
-
it 'Abort queued
|
490
|
-
process = create
|
521
|
+
it 'Abort queued After error' do
|
522
|
+
process = create AbortQueuedAfterErrorJob
|
491
523
|
|
492
524
|
process.enqueue
|
493
525
|
|
494
526
|
execute queue
|
495
527
|
|
496
|
-
process.full_status.must_equal '
|
497
|
-
'
|
498
|
-
'
|
499
|
-
'
|
500
|
-
'
|
528
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
529
|
+
'AbortQueuedAfterErrorJob::Child_1' => :queued,
|
530
|
+
'AbortQueuedAfterErrorJob::Child_2' => :queued,
|
531
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
532
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
501
533
|
|
502
534
|
execute queue
|
503
535
|
|
504
|
-
process.full_status.must_equal '
|
505
|
-
'
|
536
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
537
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
506
538
|
'Child_1_1' => :queued,
|
507
539
|
'Child_1_2' => :queued,
|
508
|
-
'
|
509
|
-
'
|
510
|
-
'
|
540
|
+
'AbortQueuedAfterErrorJob::Child_2' => :queued,
|
541
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
542
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
511
543
|
|
512
544
|
execute queue
|
513
545
|
|
514
|
-
process.full_status.must_equal '
|
515
|
-
'
|
546
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :waiting,
|
547
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
516
548
|
'Child_1_1' => :queued,
|
517
549
|
'Child_1_2' => :queued,
|
518
|
-
'
|
519
|
-
'
|
520
|
-
'
|
550
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
551
|
+
'AbortQueuedAfterErrorJob::Child_3' => :queued,
|
552
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
521
553
|
|
522
554
|
execute queue
|
523
555
|
|
524
|
-
process.full_status.must_equal '
|
525
|
-
'
|
556
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
557
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
526
558
|
'Child_1_1' => :queued,
|
527
559
|
'Child_1_2' => :queued,
|
528
|
-
'
|
529
|
-
'
|
530
|
-
'
|
560
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
561
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
562
|
+
'AbortQueuedAfterErrorJob::Child_4' => :queued
|
531
563
|
|
532
564
|
execute queue
|
533
565
|
|
534
|
-
process.full_status.must_equal '
|
535
|
-
'
|
566
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
567
|
+
'AbortQueuedAfterErrorJob::Child_1' => :waiting,
|
536
568
|
'Child_1_1' => :queued,
|
537
569
|
'Child_1_2' => :queued,
|
538
|
-
'
|
539
|
-
'
|
540
|
-
'
|
570
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
571
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
572
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
541
573
|
|
542
574
|
execute queue
|
543
575
|
|
544
|
-
process.full_status.must_equal '
|
545
|
-
'
|
576
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
577
|
+
'AbortQueuedAfterErrorJob::Child_1' => :aborted,
|
546
578
|
'Child_1_1' => :aborted,
|
547
579
|
'Child_1_2' => :queued,
|
548
|
-
'
|
549
|
-
'
|
550
|
-
'
|
580
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
581
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
582
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
551
583
|
|
552
584
|
execute queue
|
553
585
|
|
554
|
-
process.full_status.must_equal '
|
555
|
-
'
|
586
|
+
process.full_status.must_equal 'AbortQueuedAfterErrorJob' => :aborted,
|
587
|
+
'AbortQueuedAfterErrorJob::Child_1' => :aborted,
|
556
588
|
'Child_1_1' => :aborted,
|
557
589
|
'Child_1_2' => :aborted,
|
558
|
-
'
|
559
|
-
'
|
560
|
-
'
|
590
|
+
'AbortQueuedAfterErrorJob::Child_2' => :completed,
|
591
|
+
'AbortQueuedAfterErrorJob::Child_3' => :aborted,
|
592
|
+
'AbortQueuedAfterErrorJob::Child_4' => :aborted
|
561
593
|
|
562
594
|
process.real_error.must_equal 'Forced error'
|
595
|
+
process.processes[0].processes[1].error.message.must_equal Asynchronic::Process::AUTOMATIC_ABORTED_ERROR_MESSAGE
|
563
596
|
end
|
564
597
|
|
565
598
|
it 'Manual abort' do
|
@@ -604,7 +637,7 @@ module LifeCycleExamples
|
|
604
637
|
pid_1 = process_1.id
|
605
638
|
pid_2 = process_2.id
|
606
639
|
|
607
|
-
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal
|
640
|
+
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal 38
|
608
641
|
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal 7
|
609
642
|
|
610
643
|
process_1.destroy
|
@@ -622,42 +655,49 @@ module LifeCycleExamples
|
|
622
655
|
process_2.enqueue
|
623
656
|
execute queue
|
624
657
|
|
658
|
+
process_3 = create BasicJob
|
659
|
+
|
625
660
|
pid_1 = process_1.id
|
626
661
|
pid_2 = process_2.id
|
662
|
+
pid_3 = process_3.id
|
627
663
|
|
628
664
|
process_1.must_be_completed
|
629
665
|
process_2.must_be_waiting
|
666
|
+
process_3.must_be_pending
|
630
667
|
|
631
|
-
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal
|
632
|
-
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal
|
668
|
+
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal 53
|
669
|
+
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal 38
|
670
|
+
data_store.keys.select { |k| k.start_with? pid_3 }.count.must_equal 7
|
633
671
|
|
634
672
|
gc = Asynchronic::GarbageCollector.new env, 0.001
|
635
673
|
|
636
|
-
gc.add_condition('
|
674
|
+
gc.add_condition('Finalized', &:finalized?)
|
637
675
|
gc.add_condition('Waiting', &:waiting?)
|
638
676
|
gc.add_condition('Exception') { raise 'Invalid condition' }
|
639
677
|
|
640
|
-
gc.conditions_names.must_equal ['
|
678
|
+
gc.conditions_names.must_equal ['Finalized', 'Waiting', 'Exception']
|
641
679
|
|
642
680
|
gc.remove_condition 'Waiting'
|
643
681
|
|
644
|
-
gc.conditions_names.must_equal ['
|
682
|
+
gc.conditions_names.must_equal ['Finalized', 'Exception']
|
645
683
|
|
646
684
|
Thread.new do
|
647
685
|
sleep 0.01
|
648
686
|
gc.stop
|
649
687
|
end
|
650
688
|
|
651
|
-
|
689
|
+
Asynchronic::Process.stub_any_instance(:dead?, -> { id == pid_3 }) do
|
690
|
+
gc.start
|
691
|
+
end
|
652
692
|
|
653
693
|
data_store.keys.select { |k| k.start_with? pid_1 }.count.must_equal 0
|
654
|
-
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal
|
694
|
+
data_store.keys.select { |k| k.start_with? pid_2 }.count.must_equal 38
|
695
|
+
data_store.keys.select { |k| k.start_with? pid_3 }.count.must_equal 0
|
655
696
|
end
|
656
697
|
|
657
698
|
it 'Before finalize hook when completed' do
|
658
699
|
process = create BeforeFinalizeCompletedJob
|
659
700
|
|
660
|
-
process.must_be_initialized
|
661
701
|
queue.must_be_empty
|
662
702
|
|
663
703
|
process.enqueue
|
@@ -675,7 +715,6 @@ module LifeCycleExamples
|
|
675
715
|
it 'Before finalize hook when aborted' do
|
676
716
|
process = create BeforeFinalizeAbortedJob
|
677
717
|
|
678
|
-
process.must_be_initialized
|
679
718
|
queue.must_be_empty
|
680
719
|
|
681
720
|
process.enqueue
|
@@ -693,7 +732,6 @@ module LifeCycleExamples
|
|
693
732
|
it 'Before finalize raises exception and aborts' do
|
694
733
|
process = create BeforeFinalizeRaisesExceptionJob
|
695
734
|
|
696
|
-
process.must_be_initialized
|
697
735
|
queue.must_be_empty
|
698
736
|
|
699
737
|
process.enqueue
|
@@ -711,7 +749,6 @@ module LifeCycleExamples
|
|
711
749
|
it 'Before finalize raises exception on aborted job' do
|
712
750
|
process = create BeforeFinalizeExceptionOnAbortedJob
|
713
751
|
|
714
|
-
process.must_be_initialized
|
715
752
|
queue.must_be_empty
|
716
753
|
|
717
754
|
process.enqueue
|
@@ -726,5 +763,4 @@ module LifeCycleExamples
|
|
726
763
|
queue.must_be_empty
|
727
764
|
end
|
728
765
|
|
729
|
-
|
730
766
|
end
|
@@ -5,6 +5,7 @@ describe Asynchronic::Process, 'Life cycle - InMemory' do
|
|
5
5
|
|
6
6
|
let(:queue_engine) { Asynchronic::QueueEngine::InMemory.new }
|
7
7
|
let(:data_store) { Asynchronic::DataStore::InMemory.new }
|
8
|
+
let(:notifier) { Asynchronic::Notifier::InMemory.new }
|
8
9
|
|
9
10
|
include LifeCycleExamples
|
10
11
|
|
@@ -5,6 +5,7 @@ describe Asynchronic::Process, 'Life cycle - Redis' do
|
|
5
5
|
|
6
6
|
let(:queue_engine) { Asynchronic::QueueEngine::Ost.new }
|
7
7
|
let(:data_store) { Asynchronic::DataStore::Redis.new :asynchronic_test }
|
8
|
+
let(:notifier) { Asynchronic::Notifier::Broadcaster.new }
|
8
9
|
|
9
10
|
include LifeCycleExamples
|
10
11
|
|
@@ -31,17 +31,23 @@ module QueueEngineExamples
|
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'Listener' do
|
34
|
-
|
35
|
-
|
34
|
+
Timeout.timeout(5) do
|
35
|
+
queue.push 'msg_1'
|
36
|
+
queue.push 'msg_2'
|
36
37
|
|
37
|
-
|
38
|
+
messages = []
|
38
39
|
|
39
|
-
|
40
|
-
|
41
|
-
|
40
|
+
listener.listen(queue) do |msg|
|
41
|
+
messages << msg
|
42
|
+
listener.stop if queue.empty?
|
43
|
+
end
|
44
|
+
|
45
|
+
messages.must_equal %w(msg_1 msg_2)
|
42
46
|
end
|
47
|
+
end
|
43
48
|
|
44
|
-
|
49
|
+
it 'Active connections' do
|
50
|
+
engine.active_connections.must_equal [Asynchronic.connection_name]
|
45
51
|
end
|
46
52
|
|
47
53
|
end
|
@@ -34,5 +34,9 @@ describe Asynchronic::QueueEngine::Synchronic do
|
|
34
34
|
process.must_be_completed
|
35
35
|
process.result.must_equal '10%' => 20, '20%' => 40
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
|
+
it 'Active connections' do
|
39
|
+
Asynchronic.queue_engine.active_connections.must_equal [Asynchronic.connection_name]
|
40
|
+
end
|
41
|
+
|
38
42
|
end
|
data/spec/worker/redis_spec.rb
CHANGED
@@ -5,6 +5,7 @@ describe Asynchronic::Worker, 'Redis' do
|
|
5
5
|
|
6
6
|
let(:queue_engine) { Asynchronic::QueueEngine::Ost.new }
|
7
7
|
let(:data_store) { Asynchronic::DataStore::Redis.new :asynchronic_test}
|
8
|
+
let(:notifier) { Asynchronic::Notifier::Broadcaster.new }
|
8
9
|
|
9
10
|
after do
|
10
11
|
data_store.clear
|
metadata
CHANGED
@@ -1,43 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asynchronic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gabriel Naiman
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-08-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: ost
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '1.0'
|
20
20
|
type: :runtime
|
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: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: broadcaster
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0
|
33
|
+
version: '1.0'
|
34
34
|
type: :runtime
|
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: '0
|
40
|
+
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: class_config
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,34 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: bundler
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - "~>"
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '1.12'
|
90
|
-
type: :development
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - "~>"
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '1.12'
|
97
83
|
- !ruby/object:Gem::Dependency
|
98
84
|
name: rake
|
99
85
|
requirement: !ruby/object:Gem::Requirement
|
100
86
|
requirements:
|
101
87
|
- - "~>"
|
102
88
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
89
|
+
version: '12.0'
|
104
90
|
type: :development
|
105
91
|
prerelease: false
|
106
92
|
version_requirements: !ruby/object:Gem::Requirement
|
107
93
|
requirements:
|
108
94
|
- - "~>"
|
109
95
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
96
|
+
version: '12.0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: minitest
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -142,6 +128,20 @@ dependencies:
|
|
142
128
|
- - "~>"
|
143
129
|
- !ruby/object:Gem::Version
|
144
130
|
version: '0.0'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: minitest-stub_any_instance
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '1.0'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.0'
|
145
145
|
- !ruby/object:Gem::Dependency
|
146
146
|
name: minitest-colorin
|
147
147
|
requirement: !ruby/object:Gem::Requirement
|
@@ -243,6 +243,8 @@ files:
|
|
243
243
|
- lib/asynchronic/error.rb
|
244
244
|
- lib/asynchronic/garbage_collector.rb
|
245
245
|
- lib/asynchronic/job.rb
|
246
|
+
- lib/asynchronic/notifier/broadcaster.rb
|
247
|
+
- lib/asynchronic/notifier/in_memory.rb
|
246
248
|
- lib/asynchronic/process.rb
|
247
249
|
- lib/asynchronic/queue_engine/in_memory.rb
|
248
250
|
- lib/asynchronic/queue_engine/ost.rb
|
@@ -289,8 +291,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
289
291
|
- !ruby/object:Gem::Version
|
290
292
|
version: '0'
|
291
293
|
requirements: []
|
292
|
-
|
293
|
-
rubygems_version: 2.6.8
|
294
|
+
rubygems_version: 3.0.6
|
294
295
|
signing_key:
|
295
296
|
specification_version: 4
|
296
297
|
summary: DSL for asynchronic pipeline using queues over Redis
|