asynchronic 3.0.2 → 4.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 +4 -4
- data/.travis.yml +1 -0
- data/README.md +1 -1
- data/asynchronic.gemspec +1 -1
- data/lib/asynchronic/data_store/in_memory.rb +21 -16
- data/lib/asynchronic/data_store/key.rb +3 -3
- data/lib/asynchronic/data_store/lazy_value.rb +5 -3
- data/lib/asynchronic/data_store/redis.rb +22 -14
- data/lib/asynchronic/data_store/scoped_store.rb +18 -19
- data/lib/asynchronic/environment.rb +3 -3
- data/lib/asynchronic/error.rb +2 -3
- data/lib/asynchronic/garbage_collector.rb +2 -1
- data/lib/asynchronic/job.rb +12 -12
- data/lib/asynchronic/notifier/broadcaster.rb +8 -4
- data/lib/asynchronic/process.rb +35 -32
- data/lib/asynchronic/queue_engine/in_memory.rb +17 -11
- data/lib/asynchronic/queue_engine/ost.rb +7 -5
- data/lib/asynchronic/queue_engine/synchronic.rb +21 -9
- data/lib/asynchronic/version.rb +1 -1
- data/lib/asynchronic/worker.rb +7 -10
- data/lib/asynchronic.rb +8 -0
- data/spec/data_store/data_store_examples.rb +17 -9
- data/spec/data_store/in_memory_spec.rb +0 -2
- data/spec/data_store/key_spec.rb +1 -1
- data/spec/data_store/lazy_value_examples.rb +7 -5
- data/spec/data_store/redis_spec.rb +4 -10
- data/spec/expectations.rb +2 -2
- data/spec/facade_spec.rb +3 -3
- data/spec/jobs.rb +10 -10
- data/spec/minitest_helper.rb +5 -12
- data/spec/process/life_cycle_examples.rb +24 -22
- data/spec/process/life_cycle_in_memory_spec.rb +0 -1
- data/spec/process/life_cycle_redis_spec.rb +0 -1
- data/spec/queue_engine/in_memory_spec.rb +1 -3
- data/spec/queue_engine/ost_spec.rb +1 -7
- data/spec/queue_engine/queue_engine_examples.rb +17 -9
- data/spec/queue_engine/synchronic_spec.rb +1 -1
- data/spec/worker/in_memory_spec.rb +1 -2
- data/spec/worker/redis_spec.rb +0 -6
- data/spec/worker/worker_examples.rb +6 -4
- metadata +9 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 07ec97c040ebf5305b647eb5577c5bdb273d5b374903382fb8d0269aa50d9b2c
|
|
4
|
+
data.tar.gz: b5b53fa01eb3fa68327959cc65dc48738b56625c3ae355ba03232fddec6df590
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9590b7f7c7d6a41a340d3cb4a9f9e5960f3b0b7424b804d494abaae97889b8855a8e176815c6d8f93bc89bddb0bb264d31a94e2436f67ba8954ca27d58a69520
|
|
7
|
+
data.tar.gz: 3335e3a9732b1b9cd3f2513fcdffe42a1d0c2644290dd1e2aa369d2d2f11dd4688e911e4463b29d8bcbd98c04cfcf12c433a1d84c633f998347bcd36fc98ba27
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Asynchronic
|
|
2
2
|
|
|
3
3
|
[](https://rubygems.org/gems/asynchronic)
|
|
4
|
-
[](https://travis-ci.com/gabynaiman/asynchronic)
|
|
5
5
|
[](https://coveralls.io/r/gabynaiman/asynchronic?branch=master)
|
|
6
6
|
[](https://codeclimate.com/github/gabynaiman/asynchronic)
|
|
7
7
|
|
data/asynchronic.gemspec
CHANGED
|
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.require_paths = ['lib']
|
|
20
20
|
|
|
21
21
|
spec.add_dependency 'ost', '~> 1.0'
|
|
22
|
-
spec.add_dependency 'broadcaster', '~> 1.0'
|
|
22
|
+
spec.add_dependency 'broadcaster', '~> 1.0', '>= 1.0.2'
|
|
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'
|
|
@@ -4,51 +4,56 @@ module Asynchronic
|
|
|
4
4
|
|
|
5
5
|
include Helper
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def self.connect(object_id)
|
|
8
|
+
connections[object_id]
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.connections
|
|
12
|
+
@connections ||= {}
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
8
16
|
@hash = {}
|
|
9
17
|
@mutex = Mutex.new
|
|
10
|
-
@keys_mutex =
|
|
18
|
+
@keys_mutex = {}
|
|
11
19
|
self.class.connections[object_id] = self
|
|
12
20
|
end
|
|
13
21
|
|
|
14
22
|
def [](key)
|
|
15
|
-
Marshal.load(
|
|
23
|
+
Marshal.load(hash[key.to_s]) if hash.key? key.to_s
|
|
16
24
|
end
|
|
17
25
|
|
|
18
26
|
def []=(key, value)
|
|
19
|
-
|
|
27
|
+
mutex.synchronize { hash[key.to_s] = Marshal.dump(value) }
|
|
20
28
|
end
|
|
21
29
|
|
|
22
30
|
def delete(key)
|
|
23
|
-
|
|
31
|
+
hash.delete key.to_s
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
def delete_cascade(key)
|
|
27
|
-
keys
|
|
28
|
-
|
|
35
|
+
keys.select { |k| k.sections.first == key }
|
|
36
|
+
.each { |k| delete k }
|
|
29
37
|
end
|
|
30
38
|
|
|
31
39
|
def keys
|
|
32
|
-
|
|
40
|
+
hash.keys.map { |k| Key[k] }
|
|
33
41
|
end
|
|
34
42
|
|
|
35
43
|
def synchronize(key, &block)
|
|
36
|
-
|
|
44
|
+
mutex.synchronize do
|
|
45
|
+
keys_mutex[key] ||= Mutex.new
|
|
46
|
+
end
|
|
47
|
+
keys_mutex[key].synchronize(&block)
|
|
37
48
|
end
|
|
38
49
|
|
|
39
50
|
def connection_args
|
|
40
51
|
[object_id]
|
|
41
52
|
end
|
|
42
53
|
|
|
43
|
-
def self.connect(object_id)
|
|
44
|
-
connections[object_id]
|
|
45
|
-
end
|
|
46
|
-
|
|
47
54
|
private
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
@connections ||= {}
|
|
51
|
-
end
|
|
56
|
+
attr_reader :hash, :mutex, :keys_mutex
|
|
52
57
|
|
|
53
58
|
end
|
|
54
59
|
end
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
module Asynchronic
|
|
2
2
|
module DataStore
|
|
3
3
|
class Key < String
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
SEPARATOR = '|'
|
|
6
6
|
|
|
7
7
|
def self.[](key)
|
|
8
8
|
new key
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
def initialize(key)
|
|
12
12
|
super key.to_s
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def [](key)
|
|
16
|
-
self.class.new [self,key].join(SEPARATOR)
|
|
16
|
+
self.class.new [self, key].join(SEPARATOR)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def sections
|
|
@@ -14,11 +14,11 @@ module Asynchronic
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def inspect
|
|
17
|
-
"#<#{proxy_class} @data_store_class=#{
|
|
17
|
+
"#<#{proxy_class} @data_store_class=#{data_store_class} @data_store_connection_args=#{data_store_connection_args} @key=#{key}>"
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def data_store
|
|
21
|
-
|
|
21
|
+
data_store_class.connect(*data_store_connection_args)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def to_value
|
|
@@ -27,8 +27,10 @@ module Asynchronic
|
|
|
27
27
|
|
|
28
28
|
private
|
|
29
29
|
|
|
30
|
+
attr_reader :data_store_class, :data_store_connection_args, :key
|
|
31
|
+
|
|
30
32
|
def __getobj__
|
|
31
|
-
@value ||= data_store[
|
|
33
|
+
@value ||= data_store[key]
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
end
|
|
@@ -6,13 +6,17 @@ module Asynchronic
|
|
|
6
6
|
|
|
7
7
|
include Helper
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def self.connect(*args)
|
|
10
|
+
new(*args)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(scope, options={})
|
|
10
14
|
@scope = Key[scope]
|
|
11
|
-
@
|
|
15
|
+
@options = options
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
def [](key)
|
|
15
|
-
value =
|
|
19
|
+
value = redis.call! 'GET', scope[key]
|
|
16
20
|
value ? Marshal.load(value) : nil
|
|
17
21
|
rescue => ex
|
|
18
22
|
Asynchronic.logger.warn('Asynchronic') { ex.message }
|
|
@@ -20,39 +24,43 @@ module Asynchronic
|
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
def []=(key, value)
|
|
23
|
-
|
|
27
|
+
redis.call! 'SET', scope[key], Marshal.dump(value)
|
|
24
28
|
end
|
|
25
29
|
|
|
26
30
|
def delete(key)
|
|
27
|
-
|
|
31
|
+
redis.call! 'DEL', scope[key]
|
|
28
32
|
end
|
|
29
33
|
|
|
30
34
|
def delete_cascade(key)
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
redis.call! 'DEL', scope[key]
|
|
36
|
+
redis.call!('KEYS', scope[key]['*']).each { |k| redis.call! 'DEL', k }
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
def keys
|
|
36
|
-
|
|
40
|
+
redis.call!('KEYS', scope['*']).map { |k| Key[k].remove_first }
|
|
37
41
|
end
|
|
38
42
|
|
|
39
43
|
def synchronize(key)
|
|
40
|
-
while
|
|
44
|
+
while redis.call!('GETSET', scope[key][LOCKED], LOCKED) == LOCKED
|
|
41
45
|
sleep Asynchronic.redis_data_store_sync_timeout
|
|
42
46
|
end
|
|
43
47
|
yield
|
|
44
48
|
ensure
|
|
45
|
-
|
|
49
|
+
redis.call! 'DEL', scope[key][LOCKED]
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
def connection_args
|
|
49
|
-
[
|
|
53
|
+
[scope, options]
|
|
50
54
|
end
|
|
51
55
|
|
|
52
|
-
|
|
53
|
-
|
|
56
|
+
private
|
|
57
|
+
|
|
58
|
+
attr_reader :scope, :options
|
|
59
|
+
|
|
60
|
+
def redis
|
|
61
|
+
@redis ||= Asynchronic.establish_redis_connection options
|
|
54
62
|
end
|
|
55
|
-
|
|
63
|
+
|
|
56
64
|
end
|
|
57
65
|
end
|
|
58
66
|
end
|
|
@@ -4,34 +4,38 @@ module Asynchronic
|
|
|
4
4
|
|
|
5
5
|
include Helper
|
|
6
6
|
|
|
7
|
-
attr_reader :data_store
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
attr_reader :data_store, :scope
|
|
8
|
+
|
|
9
|
+
def self.connect(options)
|
|
10
|
+
data_store = options[:data_store_class].connect(*options[:data_store_connection_args])
|
|
11
|
+
new data_store, options[:scope]
|
|
12
|
+
end
|
|
13
|
+
|
|
10
14
|
def initialize(data_store, scope)
|
|
11
15
|
@data_store = data_store
|
|
12
16
|
@scope = Key[scope]
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def [](key)
|
|
16
|
-
|
|
20
|
+
data_store[scope[key]]
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def []=(key, value)
|
|
20
|
-
|
|
24
|
+
data_store[scope[key]] = value
|
|
21
25
|
end
|
|
22
26
|
|
|
23
27
|
def delete(key)
|
|
24
|
-
|
|
28
|
+
data_store.delete scope[key]
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
def delete_cascade
|
|
28
|
-
|
|
32
|
+
data_store.delete_cascade scope
|
|
29
33
|
end
|
|
30
34
|
|
|
31
35
|
def keys
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
data_store.keys
|
|
37
|
+
.select { |k| k.start_with? scope[''] }
|
|
38
|
+
.map { |k| Key[k].remove_first scope.sections.count }
|
|
35
39
|
end
|
|
36
40
|
|
|
37
41
|
def synchronize(key, &block)
|
|
@@ -41,20 +45,15 @@ module Asynchronic
|
|
|
41
45
|
def connection_args
|
|
42
46
|
[
|
|
43
47
|
{
|
|
44
|
-
data_store_class:
|
|
45
|
-
data_store_connection_args:
|
|
46
|
-
scope:
|
|
48
|
+
data_store_class: data_store.class,
|
|
49
|
+
data_store_connection_args: data_store.connection_args,
|
|
50
|
+
scope: scope
|
|
47
51
|
}
|
|
48
52
|
]
|
|
49
53
|
end
|
|
50
54
|
|
|
51
|
-
def self.connect(*args)
|
|
52
|
-
data_store = args[0][:data_store_class].connect *args[0][:data_store_connection_args]
|
|
53
|
-
new data_store, args[0][:scope]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
55
|
def to_s
|
|
57
|
-
"#<#{self.class} @data_store=#{
|
|
56
|
+
"#<#{self.class} @data_store=#{data_store} @scope=#{scope}>"
|
|
58
57
|
end
|
|
59
58
|
|
|
60
59
|
end
|
|
@@ -2,7 +2,7 @@ module Asynchronic
|
|
|
2
2
|
class Environment
|
|
3
3
|
|
|
4
4
|
attr_reader :queue_engine, :data_store, :notifier
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
def initialize(queue_engine, data_store, notifier)
|
|
7
7
|
@queue_engine = queue_engine
|
|
8
8
|
@data_store = data_store
|
|
@@ -14,7 +14,7 @@ module Asynchronic
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def default_queue
|
|
17
|
-
queue
|
|
17
|
+
queue queue_engine.default_queue
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def enqueue(msg, queue=nil)
|
|
@@ -28,7 +28,7 @@ module Asynchronic
|
|
|
28
28
|
def load_process(id)
|
|
29
29
|
Process.new self, id
|
|
30
30
|
end
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
def processes
|
|
33
33
|
Process.all self
|
|
34
34
|
end
|
data/lib/asynchronic/error.rb
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
module Asynchronic
|
|
2
2
|
class Error
|
|
3
3
|
|
|
4
|
-
attr_reader :message
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
attr_reader :message, :backtrace
|
|
5
|
+
|
|
7
6
|
def initialize(source)
|
|
8
7
|
@message = source.respond_to?(:message) ? source.message : source.to_s
|
|
9
8
|
@backtrace = source.respond_to?(:backtrace) ? source.backtrace : []
|
|
@@ -25,7 +25,8 @@ module Asynchronic
|
|
|
25
25
|
begin
|
|
26
26
|
processes.select(&condition).each(&:destroy)
|
|
27
27
|
rescue => ex
|
|
28
|
-
|
|
28
|
+
error_message = "#{ex.class}: #{ex.message}\n#{ex.backtrace.join("\n")}"
|
|
29
|
+
Asynchronic.logger.error('Asynchronic') { error_message }
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
32
|
|
data/lib/asynchronic/job.rb
CHANGED
|
@@ -1,18 +1,6 @@
|
|
|
1
1
|
module Asynchronic
|
|
2
2
|
class Job
|
|
3
3
|
|
|
4
|
-
def initialize(process)
|
|
5
|
-
@process = process
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
def params
|
|
9
|
-
@process.params
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def result(reference)
|
|
13
|
-
@process[reference].result
|
|
14
|
-
end
|
|
15
|
-
|
|
16
4
|
def self.queue(name=nil)
|
|
17
5
|
name ? @queue = name : @queue
|
|
18
6
|
end
|
|
@@ -23,6 +11,18 @@ module Asynchronic
|
|
|
23
11
|
process.id
|
|
24
12
|
end
|
|
25
13
|
|
|
14
|
+
def initialize(process)
|
|
15
|
+
@process = process
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def params
|
|
19
|
+
process.params
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def result(reference)
|
|
23
|
+
process[reference].result
|
|
24
|
+
end
|
|
25
|
+
|
|
26
26
|
private
|
|
27
27
|
|
|
28
28
|
attr_reader :process
|
|
@@ -8,23 +8,27 @@ module Asynchronic
|
|
|
8
8
|
end
|
|
9
9
|
|
|
10
10
|
def publish(pid, event, data=nil)
|
|
11
|
-
|
|
11
|
+
broadcaster.publish DataStore::Key[pid][event], data
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def subscribe(pid, event, &block)
|
|
15
|
-
|
|
15
|
+
broadcaster.subscribe DataStore::Key[pid][event] do |data|
|
|
16
16
|
block.call data
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
def unsubscribe(subscription_id)
|
|
21
|
-
|
|
21
|
+
broadcaster.unsubscribe subscription_id
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def unsubscribe_all
|
|
25
|
-
|
|
25
|
+
broadcaster.unsubscribe_all
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
private
|
|
29
|
+
|
|
30
|
+
attr_reader :broadcaster
|
|
31
|
+
|
|
28
32
|
end
|
|
29
33
|
end
|
|
30
34
|
end
|
data/lib/asynchronic/process.rb
CHANGED
|
@@ -19,6 +19,30 @@ module Asynchronic
|
|
|
19
19
|
|
|
20
20
|
attr_reader :id
|
|
21
21
|
|
|
22
|
+
def self.create(environment, type, params={})
|
|
23
|
+
id = params.delete(:id) || SecureRandom.uuid
|
|
24
|
+
|
|
25
|
+
Asynchronic.logger.debug('Asynchronic') { "Created process #{type} - #{id} - #{params}" }
|
|
26
|
+
|
|
27
|
+
new(environment, id) do
|
|
28
|
+
self.type = type
|
|
29
|
+
self.name = (params.delete(:alias) || type).to_s
|
|
30
|
+
self.queue = params.delete(:queue) || type.queue || parent_queue
|
|
31
|
+
self.dependencies = Array(params.delete(:dependencies)) | Array(params.delete(:dependency)) | infer_dependencies(params)
|
|
32
|
+
self.params = params
|
|
33
|
+
self.data = {}
|
|
34
|
+
pending!
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.all(environment)
|
|
39
|
+
environment.data_store.keys
|
|
40
|
+
.select { |k| k.sections.count == 2 && k.match(/created_at$/) }
|
|
41
|
+
.sort_by { |k| environment.data_store[k] }
|
|
42
|
+
.reverse
|
|
43
|
+
.map { |k| Process.new environment, k.remove_last }
|
|
44
|
+
end
|
|
45
|
+
|
|
22
46
|
def initialize(environment, id, &block)
|
|
23
47
|
@environment = environment
|
|
24
48
|
@id = DataStore::Key[id]
|
|
@@ -84,9 +108,11 @@ module Asynchronic
|
|
|
84
108
|
end
|
|
85
109
|
|
|
86
110
|
def processes
|
|
87
|
-
data_store.scoped(:processes)
|
|
88
|
-
|
|
89
|
-
|
|
111
|
+
data_store.scoped(:processes)
|
|
112
|
+
.keys
|
|
113
|
+
.select { |k| k.sections.count == 2 && k.match(/\|name$/) }
|
|
114
|
+
.sort
|
|
115
|
+
.map { |k| Process.new environment, id[:processes][k.remove_last] }
|
|
90
116
|
end
|
|
91
117
|
|
|
92
118
|
def parent
|
|
@@ -107,11 +133,11 @@ module Asynchronic
|
|
|
107
133
|
|
|
108
134
|
def dependencies
|
|
109
135
|
return [] if parent.nil? || data_store[:dependencies].empty?
|
|
110
|
-
|
|
136
|
+
|
|
111
137
|
parent_processes = parent.processes.each_with_object({}) do |process, hash|
|
|
112
138
|
hash[process.name] = process
|
|
113
139
|
end
|
|
114
|
-
|
|
140
|
+
|
|
115
141
|
data_store[:dependencies].map { |d| parent_processes[d.to_s] }
|
|
116
142
|
end
|
|
117
143
|
|
|
@@ -135,7 +161,7 @@ module Asynchronic
|
|
|
135
161
|
wakeup_children
|
|
136
162
|
end
|
|
137
163
|
Asynchronic.logger.info('Asynchronic') { "Wakeup finalized #{type} (#{id})" }
|
|
138
|
-
|
|
164
|
+
|
|
139
165
|
parent.wakeup if parent && finalized?
|
|
140
166
|
end
|
|
141
167
|
|
|
@@ -151,29 +177,6 @@ module Asynchronic
|
|
|
151
177
|
self.data = self.data.merge key => value
|
|
152
178
|
end
|
|
153
179
|
|
|
154
|
-
def self.create(environment, type, params={})
|
|
155
|
-
id = params.delete(:id) || SecureRandom.uuid
|
|
156
|
-
|
|
157
|
-
Asynchronic.logger.debug('Asynchronic') { "Created process #{type} - #{id} - #{params}" }
|
|
158
|
-
|
|
159
|
-
new(environment, id) do
|
|
160
|
-
self.type = type
|
|
161
|
-
self.name = (params.delete(:alias) || type).to_s
|
|
162
|
-
self.queue = params.delete(:queue) || type.queue || parent_queue
|
|
163
|
-
self.dependencies = Array(params.delete(:dependencies)) | Array(params.delete(:dependency)) | infer_dependencies(params)
|
|
164
|
-
self.params = params
|
|
165
|
-
self.data = {}
|
|
166
|
-
pending!
|
|
167
|
-
end
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def self.all(environment)
|
|
171
|
-
environment.data_store.keys.
|
|
172
|
-
select { |k| k.sections.count == 2 && k.match(/created_at$/) }.
|
|
173
|
-
sort_by { |k| environment.data_store[k] }.reverse.
|
|
174
|
-
map { |k| Process.new environment, k.remove_last }
|
|
175
|
-
end
|
|
176
|
-
|
|
177
180
|
private
|
|
178
181
|
|
|
179
182
|
attr_reader :environment
|
|
@@ -194,10 +197,10 @@ module Asynchronic
|
|
|
194
197
|
|
|
195
198
|
def status=(status)
|
|
196
199
|
Asynchronic.logger.info('Asynchronic') { "#{status.to_s.capitalize} #{type} (#{id})" }
|
|
197
|
-
|
|
200
|
+
|
|
198
201
|
data_store[:status] = status
|
|
199
202
|
data_store[TIME_TRACKING_MAP[status]] = Time.now if TIME_TRACKING_MAP.key? status
|
|
200
|
-
|
|
203
|
+
|
|
201
204
|
environment.notifier.publish id, :status_changed, status
|
|
202
205
|
environment.notifier.publish id, :finalized if finalized?
|
|
203
206
|
end
|
|
@@ -229,7 +232,7 @@ module Asynchronic
|
|
|
229
232
|
self.result = job.call
|
|
230
233
|
waiting!
|
|
231
234
|
end
|
|
232
|
-
|
|
235
|
+
|
|
233
236
|
rescue Exception => ex
|
|
234
237
|
message = "Failed process #{type} (#{id})\n#{ex.class} #{ex.message}\n#{ex.backtrace.join("\n")}"
|
|
235
238
|
Asynchronic.logger.error('Asynchronic') { message }
|
|
@@ -2,27 +2,25 @@ module Asynchronic
|
|
|
2
2
|
module QueueEngine
|
|
3
3
|
class InMemory
|
|
4
4
|
|
|
5
|
-
attr_reader :default_queue
|
|
6
|
-
|
|
7
5
|
def initialize(options={})
|
|
8
|
-
@
|
|
6
|
+
@options = options
|
|
9
7
|
@queues ||= Hash.new { |h,k| h[k] = Queue.new }
|
|
10
8
|
end
|
|
11
9
|
|
|
12
10
|
def default_queue
|
|
13
|
-
@default_queue ||= Asynchronic.default_queue
|
|
11
|
+
@default_queue ||= options.fetch(:default_queue, Asynchronic.default_queue)
|
|
14
12
|
end
|
|
15
13
|
|
|
16
14
|
def [](name)
|
|
17
|
-
|
|
15
|
+
queues[name]
|
|
18
16
|
end
|
|
19
17
|
|
|
20
|
-
def
|
|
21
|
-
|
|
18
|
+
def queue_names
|
|
19
|
+
queues.keys.map(&:to_sym)
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
def clear
|
|
25
|
-
|
|
23
|
+
queues.clear
|
|
26
24
|
end
|
|
27
25
|
|
|
28
26
|
def listener
|
|
@@ -37,12 +35,16 @@ module Asynchronic
|
|
|
37
35
|
[Asynchronic.connection_name]
|
|
38
36
|
end
|
|
39
37
|
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
attr_reader :queues, :options
|
|
41
|
+
|
|
40
42
|
|
|
41
43
|
class Queue
|
|
42
44
|
|
|
43
45
|
extend Forwardable
|
|
44
46
|
|
|
45
|
-
def_delegators
|
|
47
|
+
def_delegators :queue, :size, :empty?, :to_a
|
|
46
48
|
|
|
47
49
|
def initialize
|
|
48
50
|
@queue = []
|
|
@@ -50,13 +52,17 @@ module Asynchronic
|
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
def pop
|
|
53
|
-
|
|
55
|
+
mutex.synchronize { queue.shift }
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def push(message)
|
|
57
|
-
|
|
59
|
+
mutex.synchronize { queue.push message }
|
|
58
60
|
end
|
|
59
61
|
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
attr_reader :queue, :mutex
|
|
65
|
+
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
|
|
@@ -5,22 +5,22 @@ module Asynchronic
|
|
|
5
5
|
attr_reader :redis, :default_queue
|
|
6
6
|
|
|
7
7
|
def initialize(options={})
|
|
8
|
-
@redis =
|
|
8
|
+
@redis = Asynchronic.establish_redis_connection options
|
|
9
9
|
@default_queue = options.fetch(:default_queue, Asynchronic.default_queue)
|
|
10
10
|
@queues ||= Hash.new { |h,k| h[k] = Queue.new k, redis }
|
|
11
11
|
@keep_alive_thread = notify_keep_alive
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def [](name)
|
|
15
|
-
|
|
15
|
+
queues[name]
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
-
def
|
|
19
|
-
(
|
|
18
|
+
def queue_names
|
|
19
|
+
(queues.values.map(&:key) | redis.call!('KEYS', 'ost:*')).map { |q| q.to_s[4..-1].to_sym }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def clear
|
|
23
|
-
|
|
23
|
+
queues.clear
|
|
24
24
|
redis.call!('KEYS', 'ost:*').each { |k| redis.call!('DEL', k) }
|
|
25
25
|
end
|
|
26
26
|
|
|
@@ -41,6 +41,8 @@ module Asynchronic
|
|
|
41
41
|
|
|
42
42
|
private
|
|
43
43
|
|
|
44
|
+
attr_reader :queues
|
|
45
|
+
|
|
44
46
|
def notify_keep_alive
|
|
45
47
|
Thread.new do
|
|
46
48
|
loop do
|