thomas_utils 0.1.18 → 0.2.3
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/lib/thomas_utils.rb +3 -0
- data/lib/thomas_utils/constant_var.rb +47 -0
- data/lib/thomas_utils/executor_service.rb +7 -0
- data/lib/thomas_utils/future.rb +40 -29
- data/lib/thomas_utils/observation.rb +167 -0
- metadata +7 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1020f2a07e22d03f1be48e6c97fdc68b4c03631b
|
4
|
+
data.tar.gz: 35873e679f97bab51c4cad7b613efeca95733a60
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2cd4e5f2b799142ea45e3ad1026fd748cfa2e2520072d3a0ca836b61b98dd39e3db42d61f3a88f72f1ec70168fe34d94e6ceb8f020e6a36f54715d057789d029
|
7
|
+
data.tar.gz: a511baf55abad9d03c3f8f70ce972fad75e3defd6c2b46c1b58235c940450d7e15e74c262062d5f76f02444097202eb9f5b46ba61cc0b468d59495db5ad15c96
|
data/lib/thomas_utils.rb
CHANGED
@@ -25,4 +25,7 @@ require 'thomas_utils/multi_future_wrapper'
|
|
25
25
|
require 'thomas_utils/key_comparer'
|
26
26
|
require 'thomas_utils/key_indexer'
|
27
27
|
require 'thomas_utils/key_child'
|
28
|
+
require 'thomas_utils/executor_service'
|
29
|
+
require 'thomas_utils/constant_var'
|
30
|
+
require 'thomas_utils/observation'
|
28
31
|
require 'thomas_utils/future'
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module ThomasUtils
|
2
|
+
class ConstantVar < Struct.new(:time, :value, :reason)
|
3
|
+
|
4
|
+
def self.value(value)
|
5
|
+
new(Time.now, value, nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.none
|
9
|
+
new(Time.now, nil, nil)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.error(error)
|
13
|
+
new(Time.now, nil, error)
|
14
|
+
end
|
15
|
+
|
16
|
+
def value!
|
17
|
+
raise reason if reason
|
18
|
+
value
|
19
|
+
end
|
20
|
+
|
21
|
+
def add_observer(observer = nil, func = :update, &block)
|
22
|
+
if block
|
23
|
+
observer = block
|
24
|
+
func = :call
|
25
|
+
end
|
26
|
+
observer.public_send(func, time, value, reason)
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_observer(observer = nil, func = :update, &block)
|
30
|
+
add_observer(observer, func, &block)
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_observer(_)
|
35
|
+
raise NotImplementedError
|
36
|
+
end
|
37
|
+
|
38
|
+
def delete_observers
|
39
|
+
raise NotImplementedError
|
40
|
+
end
|
41
|
+
|
42
|
+
def count_observers
|
43
|
+
raise NotImplementedError
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
data/lib/thomas_utils/future.rb
CHANGED
@@ -1,42 +1,53 @@
|
|
1
1
|
module ThomasUtils
|
2
|
-
class Future
|
2
|
+
class Future < Observation
|
3
3
|
DEFAULT_EXECUTOR = ::Concurrent::CachedThreadPool.new
|
4
|
+
IMMEDIATE_EXECUTOR = ::Concurrent::ImmediateExecutor.new
|
4
5
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@result = yield
|
12
|
-
@result = @result.get if @result.is_a?(FutureWrapper)
|
13
|
-
@mutex.synchronize { @success_callback.call(@result) if @success_callback }
|
14
|
-
@result
|
15
|
-
rescue => e
|
16
|
-
@error = e
|
17
|
-
@mutex.synchronize { @failure_callback.call(e) if @failure_callback }
|
18
|
-
end
|
19
|
-
end
|
6
|
+
def self.value(value)
|
7
|
+
Observation.new(IMMEDIATE_EXECUTOR, ConstantVar.value(value))
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.immediate(&block)
|
11
|
+
none.then(&block)
|
20
12
|
end
|
21
13
|
|
22
|
-
def
|
23
|
-
|
24
|
-
raise @error if @error
|
25
|
-
result
|
14
|
+
def self.none
|
15
|
+
Observation.new(IMMEDIATE_EXECUTOR, ConstantVar.none)
|
26
16
|
end
|
27
17
|
|
28
|
-
def
|
29
|
-
|
18
|
+
def self.error(error)
|
19
|
+
Observation.new(IMMEDIATE_EXECUTOR, ConstantVar.error(error))
|
30
20
|
end
|
31
21
|
|
32
|
-
def
|
33
|
-
|
34
|
-
|
22
|
+
def self.all(observations)
|
23
|
+
observable = Concurrent::IVar.new
|
24
|
+
left = observations.count
|
25
|
+
buffer = [nil] * left
|
26
|
+
mutex = Mutex.new
|
27
|
+
observations.each_with_index do |observation, index|
|
28
|
+
observation.on_complete do |value, error|
|
29
|
+
if error
|
30
|
+
observable.fail(error)
|
31
|
+
else
|
32
|
+
buffer[index] = value
|
33
|
+
done = false
|
34
|
+
mutex.synchronize do
|
35
|
+
left -= 1
|
36
|
+
done = !!left.zero?
|
37
|
+
end
|
38
|
+
observable.set(buffer) if done
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
Observation.new(DEFAULT_EXECUTOR, observable)
|
35
43
|
end
|
36
44
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
45
|
+
def initialize(options = {}, &block)
|
46
|
+
executor = options.fetch(:executor) { DEFAULT_EXECUTOR }
|
47
|
+
observable = Concurrent::Future.execute(executor: executor, &block)
|
48
|
+
super(executor, observable)
|
40
49
|
end
|
50
|
+
|
41
51
|
end
|
42
|
-
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,167 @@
|
|
1
|
+
module ThomasUtils
|
2
|
+
class Observation
|
3
|
+
extend Forwardable
|
4
|
+
|
5
|
+
def_delegator :@observable, :value!, :get
|
6
|
+
|
7
|
+
def initialize(executor, observable)
|
8
|
+
@executor = executor
|
9
|
+
@observable = observable
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_success
|
13
|
+
@observable.add_observer do |_, value, error|
|
14
|
+
@executor.post do
|
15
|
+
yield value unless error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def on_failure
|
22
|
+
@observable.add_observer do |_, _, error|
|
23
|
+
@executor.post do
|
24
|
+
yield error if error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_complete
|
31
|
+
@observable.add_observer do |_, value, error|
|
32
|
+
@executor.post do
|
33
|
+
yield value, error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def join
|
40
|
+
@observable.value
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def then(&block)
|
45
|
+
successive(:on_complete_then, &block)
|
46
|
+
end
|
47
|
+
|
48
|
+
def none_fallback
|
49
|
+
self.then do |result|
|
50
|
+
result || yield
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def fallback(&block)
|
55
|
+
successive(:on_complete_fallback, &block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def ensure(&block)
|
59
|
+
successive(:on_complete_ensure, &block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def on_success_ensure(&block)
|
63
|
+
self.then do |result|
|
64
|
+
child_result = block.call(result)
|
65
|
+
if result_is_observation?(child_result)
|
66
|
+
child_result.then { result }
|
67
|
+
else
|
68
|
+
result
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def on_failure_ensure(&block)
|
74
|
+
self.fallback do |error|
|
75
|
+
result = block.call(error)
|
76
|
+
error_observation = Observation.new(@executor, ConstantVar.error(error))
|
77
|
+
if result_is_observation?(result)
|
78
|
+
result.then { error_observation }
|
79
|
+
else
|
80
|
+
error_observation
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def successive(method, &block)
|
88
|
+
observable = Concurrent::IVar.new
|
89
|
+
send(method, observable, &block)
|
90
|
+
Observation.new(@executor, observable)
|
91
|
+
end
|
92
|
+
|
93
|
+
def on_complete_then(observable, &block)
|
94
|
+
on_complete do |value, error|
|
95
|
+
if error
|
96
|
+
observable.fail(error)
|
97
|
+
else
|
98
|
+
on_success_then(observable, value, &block)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def on_complete_fallback(observable, &block)
|
104
|
+
on_complete do |value, error|
|
105
|
+
if error
|
106
|
+
on_failure_fallback(observable, error, &block)
|
107
|
+
else
|
108
|
+
observable.set(value)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def on_success_then(observable, value)
|
114
|
+
result = yield value
|
115
|
+
if result_is_observation?(result)
|
116
|
+
result.on_complete do |child_result, child_error|
|
117
|
+
ensure_then(child_error, observable, child_result)
|
118
|
+
end
|
119
|
+
else
|
120
|
+
observable.set(result)
|
121
|
+
end
|
122
|
+
rescue Exception => error
|
123
|
+
observable.fail(error)
|
124
|
+
end
|
125
|
+
|
126
|
+
alias :on_failure_fallback :on_success_then
|
127
|
+
|
128
|
+
def on_complete_ensure(observable)
|
129
|
+
on_complete do |value, error|
|
130
|
+
begin
|
131
|
+
result = yield value, error
|
132
|
+
if result_is_observation?(result)
|
133
|
+
ensure_complete_then(error, observable, result, value)
|
134
|
+
else
|
135
|
+
ensure_then(error, observable, value)
|
136
|
+
end
|
137
|
+
rescue Exception => child_error
|
138
|
+
observable.fail(child_error)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def ensure_complete_then(error, observable, result, value)
|
144
|
+
result.on_complete do |_, child_error|
|
145
|
+
if child_error
|
146
|
+
observable.fail(child_error)
|
147
|
+
elsif error
|
148
|
+
observable.fail(error)
|
149
|
+
else
|
150
|
+
observable.set(value)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def ensure_then(error, observable, value)
|
156
|
+
if error
|
157
|
+
observable.fail(error)
|
158
|
+
else
|
159
|
+
observable.set(value)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def result_is_observation?(result)
|
164
|
+
result.respond_to?(:on_complete) && result.respond_to?(:then)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thomas_utils
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas RM Rogers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ~>
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 1.0.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.0
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: workers
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,6 +50,8 @@ files:
|
|
50
50
|
- LICENSE.txt
|
51
51
|
- README.md
|
52
52
|
- lib/thomas_utils.rb
|
53
|
+
- lib/thomas_utils/constant_var.rb
|
54
|
+
- lib/thomas_utils/executor_service.rb
|
53
55
|
- lib/thomas_utils/future.rb
|
54
56
|
- lib/thomas_utils/future_wrapper.rb
|
55
57
|
- lib/thomas_utils/key_child.rb
|
@@ -57,6 +59,7 @@ files:
|
|
57
59
|
- lib/thomas_utils/key_indexer.rb
|
58
60
|
- lib/thomas_utils/multi_future_wrapper.rb
|
59
61
|
- lib/thomas_utils/object_stream.rb
|
62
|
+
- lib/thomas_utils/observation.rb
|
60
63
|
- lib/thomas_utils/periodic_flusher.rb
|
61
64
|
- lib/thomas_utils/symbol_helpers.rb
|
62
65
|
homepage: https://www.github.com/thomasrogers03/thomas_utils
|