mr_darcy 0.1.0 → 0.2.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/.travis.yml +1 -2
- data/lib/mr_darcy.rb +8 -2
- data/lib/mr_darcy/context.rb +1 -1
- data/lib/mr_darcy/deferred.rb +3 -2
- data/lib/mr_darcy/promise.rb +2 -1
- data/lib/mr_darcy/promise/base.rb +54 -18
- data/lib/mr_darcy/promise/celluloid.rb +76 -16
- data/lib/mr_darcy/promise/child_promise.rb +24 -19
- data/lib/mr_darcy/promise/em.rb +56 -5
- data/lib/mr_darcy/promise/state/base.rb +2 -2
- data/lib/mr_darcy/promise/thread.rb +38 -19
- data/lib/mr_darcy/role.rb +26 -6
- data/lib/mr_darcy/version.rb +1 -1
- data/spec/acceptance/dci_bank_transfer_spec.rb +12 -16
- data/spec/acceptance/em_http_request_spec.rb +20 -17
- data/spec/acceptance/simple_promise_with_fail_spec.rb +2 -2
- data/spec/lib/mr_darcy/promise/base_spec.rb +1 -1
- data/spec/lib/mr_darcy/promise/child_promise_spec.rb +23 -27
- data/spec/lib/mr_darcy/promise/em_spec.rb +20 -0
- data/spec/lib/mr_darcy/promise_spec.rb +35 -11
- data/spec/lib/mr_darcy/role_spec.rb +1 -1
- data/spec/lib/mr_darcy_spec.rb +20 -0
- metadata +46 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76e4be46dc9cdd1c3940172e1fd429cb9ca06d1e
|
4
|
+
data.tar.gz: c8f1944c3cf626b51599edf3337a66bc146969c6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37ea3db8c56a22d1f78ab6f004c06e4b4f96e98f5fb95a8824fd2adc7491c40fa957546008c8d98bfdd7899739b9d2df29e2cd48e4d51da966305dc756dc95aa
|
7
|
+
data.tar.gz: 3fdde3baecf7aa7fcb3a1b925084b09be2b742a405326344c83b644b9b4c21812b557ae17a3a3a0dfbdf4f8db1656dfb4ecd6016cf10c939667ad7da71dadf7e
|
data/.travis.yml
CHANGED
data/lib/mr_darcy.rb
CHANGED
@@ -17,10 +17,16 @@ module MrDarcy
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def all_drivers
|
20
|
-
%w| synchronous thread celluloid em |.map(&:to_sym)
|
20
|
+
drivers = %w| synchronous thread celluloid em |.map(&:to_sym)
|
21
|
+
|
22
|
+
drivers.delete :em if RUBY_ENGINE=='jruby'
|
23
|
+
|
24
|
+
drivers
|
21
25
|
end
|
22
26
|
|
23
|
-
def promise
|
27
|
+
def promise opts={}, &block
|
28
|
+
driver = opts[:driver] || self.driver
|
24
29
|
MrDarcy::Promise.new driver: driver, &block
|
25
30
|
end
|
31
|
+
|
26
32
|
end
|
data/lib/mr_darcy/context.rb
CHANGED
@@ -28,7 +28,7 @@ module MrDarcy
|
|
28
28
|
roles = self.class.roles
|
29
29
|
roles.each do |role_name, role|
|
30
30
|
player = role_players[role_name]
|
31
|
-
raise ArgumentError, "No role player for #{role_name} supplied" unless player
|
31
|
+
Kernel::raise ArgumentError, "No role player for #{role_name} supplied" unless player
|
32
32
|
|
33
33
|
role.pollute(player)
|
34
34
|
|
data/lib/mr_darcy/deferred.rb
CHANGED
@@ -5,7 +5,7 @@ module MrDarcy
|
|
5
5
|
|
6
6
|
%w| resolved? rejected? unresolved? resolve reject final result |.map(&:to_sym).each do |method|
|
7
7
|
define_method method do |*args|
|
8
|
-
|
8
|
+
last_promise.public_send method, *args
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
@@ -17,7 +17,8 @@ module MrDarcy
|
|
17
17
|
self.last_promise = last_promise.fail(&block)
|
18
18
|
end
|
19
19
|
|
20
|
-
def initialize
|
20
|
+
def initialize opts={}
|
21
|
+
driver = opts[:driver] || MrDarcy.driver
|
21
22
|
self.promise = MrDarcy::Promise.new(driver: driver) {}
|
22
23
|
self.last_promise = promise
|
23
24
|
end
|
data/lib/mr_darcy/promise.rb
CHANGED
@@ -7,21 +7,20 @@ module MrDarcy
|
|
7
7
|
schedule_promise do
|
8
8
|
evaluate_promise &block
|
9
9
|
end
|
10
|
+
did_initialize
|
10
11
|
end
|
11
12
|
|
12
13
|
def then &block
|
13
|
-
|
14
|
+
ensure_child_promise
|
14
15
|
child_promise.resolve_block = block
|
15
|
-
|
16
|
-
reject_child_promise if rejected?
|
16
|
+
resolve_or_reject_child_as_needed
|
17
17
|
child_promise.promise
|
18
18
|
end
|
19
19
|
|
20
20
|
def fail &block
|
21
|
-
|
21
|
+
ensure_child_promise
|
22
22
|
child_promise.reject_block = block
|
23
|
-
|
24
|
-
reject_child_promise if rejected?
|
23
|
+
resolve_or_reject_child_as_needed
|
25
24
|
child_promise.promise
|
26
25
|
end
|
27
26
|
|
@@ -35,7 +34,13 @@ module MrDarcy
|
|
35
34
|
|
36
35
|
def raise
|
37
36
|
r = result
|
38
|
-
|
37
|
+
if rejected?
|
38
|
+
if r.is_a? Exception
|
39
|
+
super r
|
40
|
+
else
|
41
|
+
super RuntimeError, r
|
42
|
+
end
|
43
|
+
end
|
39
44
|
end
|
40
45
|
|
41
46
|
%w| resolved? unresolved? rejected? |.map(&:to_sym).each do |method|
|
@@ -45,20 +50,40 @@ module MrDarcy
|
|
45
50
|
end
|
46
51
|
|
47
52
|
def resolve value
|
53
|
+
do_resolve value
|
54
|
+
self
|
55
|
+
end
|
56
|
+
|
57
|
+
def reject exception
|
58
|
+
do_reject exception
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
attr_accessor :value, :state
|
65
|
+
|
66
|
+
def do_resolve value
|
67
|
+
will_resolve value
|
48
68
|
set_value_to value
|
49
69
|
state_machine_resolve
|
50
70
|
resolve_child_promise
|
71
|
+
did_resolve value
|
51
72
|
end
|
52
73
|
|
53
|
-
def
|
74
|
+
def do_reject exception
|
75
|
+
will_reject value
|
54
76
|
set_value_to exception
|
55
77
|
state_machine_reject
|
56
78
|
reject_child_promise
|
79
|
+
did_reject value
|
57
80
|
end
|
58
81
|
|
59
|
-
|
60
|
-
|
61
|
-
|
82
|
+
def will_resolve value; end
|
83
|
+
def will_reject value; end
|
84
|
+
def did_resolve value; end
|
85
|
+
def did_reject value; end
|
86
|
+
def did_initialize; end
|
62
87
|
|
63
88
|
def state
|
64
89
|
@state ||= :unresolved
|
@@ -85,15 +110,16 @@ module MrDarcy
|
|
85
110
|
end
|
86
111
|
|
87
112
|
def resolve_child_promise
|
88
|
-
|
89
|
-
child_promise.parent_resolved(value) if has_child_promise?
|
90
|
-
end
|
113
|
+
child_promise.parent_resolved(value) if has_child_promise?
|
91
114
|
end
|
92
115
|
|
93
116
|
def reject_child_promise
|
94
|
-
|
95
|
-
|
96
|
-
|
117
|
+
child_promise.parent_rejected(value) if has_child_promise?
|
118
|
+
end
|
119
|
+
|
120
|
+
def resolve_or_reject_child_as_needed
|
121
|
+
resolve_child_promise if resolved?
|
122
|
+
reject_child_promise if rejected?
|
97
123
|
end
|
98
124
|
|
99
125
|
def schedule_promise
|
@@ -102,7 +128,9 @@ module MrDarcy
|
|
102
128
|
|
103
129
|
def evaluate_promise &block
|
104
130
|
begin
|
105
|
-
|
131
|
+
dsl = DSL.new(self)
|
132
|
+
dsl.instance_exec dsl, &block
|
133
|
+
# block.call DSL.new(self)
|
106
134
|
rescue Exception => e
|
107
135
|
reject e
|
108
136
|
end
|
@@ -112,6 +140,14 @@ module MrDarcy
|
|
112
140
|
Kernel::raise "Subclasses must implement me"
|
113
141
|
end
|
114
142
|
|
143
|
+
def ensure_child_promise
|
144
|
+
@child_promise ||= generate_child_promise
|
145
|
+
end
|
146
|
+
|
147
|
+
def child_promise
|
148
|
+
@child_promise
|
149
|
+
end
|
150
|
+
|
115
151
|
end
|
116
152
|
end
|
117
153
|
end
|
@@ -3,50 +3,110 @@ require 'celluloid/autostart'
|
|
3
3
|
module MrDarcy
|
4
4
|
module Promise
|
5
5
|
class Celluloid < Base
|
6
|
+
class Actor
|
7
|
+
include ::Celluloid
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@complete = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def schedule block
|
14
|
+
::Celluloid::Future.new &block
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_status status, value
|
18
|
+
case status
|
19
|
+
when :success
|
20
|
+
@success.call value
|
21
|
+
when :failure
|
22
|
+
@failure.call value
|
23
|
+
end
|
24
|
+
signal :complete
|
25
|
+
@complete = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_success block
|
29
|
+
@success = block
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_failure block
|
33
|
+
@failure = block
|
34
|
+
end
|
35
|
+
|
36
|
+
def await_completion
|
37
|
+
return if @complete
|
38
|
+
wait :complete
|
39
|
+
end
|
40
|
+
end
|
6
41
|
|
7
42
|
def initialize *args
|
8
|
-
@
|
43
|
+
@complete = false
|
44
|
+
ensure_actor
|
45
|
+
actor.on_success proc { |v| do_resolve v }
|
46
|
+
actor.on_failure proc { |v| do_reject v }
|
9
47
|
super
|
10
48
|
end
|
11
49
|
|
12
50
|
def resolve value
|
13
|
-
|
14
|
-
|
51
|
+
actor.async.set_status :success, value
|
52
|
+
self
|
15
53
|
end
|
16
54
|
|
17
|
-
def reject
|
18
|
-
|
19
|
-
|
55
|
+
def reject value
|
56
|
+
actor.async.set_status :failure, value
|
57
|
+
self
|
20
58
|
end
|
21
59
|
|
22
60
|
def result
|
23
|
-
|
61
|
+
wait_until_complete
|
24
62
|
value
|
25
63
|
end
|
26
64
|
|
27
65
|
def final
|
28
|
-
|
66
|
+
wait_until_complete
|
29
67
|
self
|
30
68
|
end
|
31
69
|
|
32
70
|
private
|
33
71
|
|
34
|
-
def
|
35
|
-
|
72
|
+
def wait_until_complete
|
73
|
+
return if @complete
|
74
|
+
actor.alive? && actor.await_completion
|
75
|
+
@complete = true
|
36
76
|
end
|
37
77
|
|
38
|
-
def
|
39
|
-
@
|
78
|
+
def will_resolve value
|
79
|
+
@complete = true
|
40
80
|
end
|
41
81
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
82
|
+
def will_reject value
|
83
|
+
@complete = true
|
84
|
+
end
|
85
|
+
|
86
|
+
def did_reject value
|
87
|
+
actor.async.terminate
|
88
|
+
end
|
89
|
+
|
90
|
+
def did_resolve value
|
91
|
+
actor.async.terminate
|
45
92
|
end
|
46
93
|
|
47
94
|
def generate_child_promise
|
48
|
-
ChildPromise.new driver: :
|
95
|
+
ChildPromise.new driver: :celluloid
|
96
|
+
end
|
97
|
+
|
98
|
+
def ensure_actor
|
99
|
+
@actor ||= Actor.new
|
49
100
|
end
|
101
|
+
|
102
|
+
def actor
|
103
|
+
@actor
|
104
|
+
end
|
105
|
+
|
106
|
+
def schedule_promise &block
|
107
|
+
actor.async.schedule block
|
108
|
+
end
|
109
|
+
|
50
110
|
end
|
51
111
|
end
|
52
112
|
end
|
@@ -1,44 +1,49 @@
|
|
1
1
|
module MrDarcy
|
2
2
|
module Promise
|
3
|
-
class ChildPromise
|
3
|
+
class ChildPromise
|
4
4
|
|
5
|
-
attr_accessor :resolve_block, :reject_block
|
5
|
+
attr_accessor :resolve_block, :reject_block, :promise
|
6
6
|
|
7
7
|
def initialize opts={}
|
8
|
-
|
9
|
-
super
|
8
|
+
self.promise = MrDarcy.promise(opts) {}
|
10
9
|
end
|
11
10
|
|
12
11
|
def parent_resolved value
|
13
12
|
begin
|
14
13
|
return resolve_with value unless handles_resolve?
|
14
|
+
|
15
15
|
new_value = result_for :resolve, value
|
16
|
-
if thenable? new_value
|
17
|
-
|
18
|
-
else
|
19
|
-
resolve_with new_value
|
20
|
-
end
|
16
|
+
return defer_resolution_via new_value if thenable? new_value
|
17
|
+
resolve_with new_value
|
21
18
|
rescue Exception => e
|
22
|
-
|
19
|
+
handle_exception e
|
23
20
|
end
|
24
21
|
end
|
25
22
|
|
26
23
|
def parent_rejected value
|
27
24
|
begin
|
28
25
|
return reject_with value unless handles_reject?
|
26
|
+
|
29
27
|
new_value = result_for :reject, value
|
30
|
-
if thenable? new_value
|
31
|
-
|
32
|
-
else
|
33
|
-
resolve_with new_value
|
34
|
-
end
|
28
|
+
return defer_resolution_via new_value if thenable? new_value
|
29
|
+
resolve_with new_value
|
35
30
|
rescue Exception => e
|
36
|
-
|
31
|
+
handle_exception e
|
37
32
|
end
|
38
33
|
end
|
39
34
|
|
40
35
|
private
|
41
36
|
|
37
|
+
def handle_exception e
|
38
|
+
if promise.unresolved?
|
39
|
+
return reject_with e
|
40
|
+
elsif promise.resolved?
|
41
|
+
promise.then { raise e }
|
42
|
+
elsif promise.rejected?
|
43
|
+
promise.fail { raise e }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
42
47
|
def result_for which, value
|
43
48
|
block = public_send("#{which}_block")
|
44
49
|
if block
|
@@ -60,12 +65,12 @@ module MrDarcy
|
|
60
65
|
object.respond_to?(:then) && object.respond_to?(:fail)
|
61
66
|
end
|
62
67
|
|
63
|
-
def defer_resolution_via
|
64
|
-
|
68
|
+
def defer_resolution_via new_promise
|
69
|
+
new_promise.then do |value|
|
65
70
|
resolve_with value
|
66
71
|
value
|
67
72
|
end
|
68
|
-
|
73
|
+
new_promise.fail do |exception|
|
69
74
|
reject_with exception
|
70
75
|
exception
|
71
76
|
end
|
data/lib/mr_darcy/promise/em.rb
CHANGED
@@ -2,28 +2,79 @@ require 'eventmachine'
|
|
2
2
|
|
3
3
|
module MrDarcy
|
4
4
|
module Promise
|
5
|
-
class EM <
|
5
|
+
class EM < Base
|
6
|
+
class DeferrableAdapter
|
7
|
+
include EventMachine::Deferrable
|
8
|
+
end
|
6
9
|
|
7
10
|
def initialize *args
|
11
|
+
Kernel::raise "EventMachine driver is unsupported on JRuby, sorry" if RUBY_ENGINE=='jruby'
|
8
12
|
unless EventMachine.reactor_running?
|
9
13
|
::Thread.new { EventMachine.run }
|
10
14
|
::Thread.pass until EventMachine.reactor_running?
|
11
15
|
end
|
16
|
+
@wait_lock = Mutex.new
|
17
|
+
@wait_cond = ConditionVariable.new
|
18
|
+
@wait_lock.lock
|
19
|
+
deferrable_adapter.callback &method(:do_resolve)
|
20
|
+
deferrable_adapter.errback &method(:do_reject)
|
12
21
|
super
|
13
22
|
end
|
14
23
|
|
24
|
+
def resolve value
|
25
|
+
deferrable_adapter.set_deferred_status :succeeded, value
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def reject value
|
30
|
+
deferrable_adapter.set_deferred_status :failed, value
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
def result
|
35
|
+
wait_if_unresolved
|
36
|
+
value
|
37
|
+
end
|
38
|
+
|
39
|
+
def final
|
40
|
+
wait_if_unresolved
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
15
44
|
private
|
16
45
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
46
|
+
def wait_if_unresolved
|
47
|
+
@wait_cond.wait @wait_lock if unresolved?
|
48
|
+
end
|
49
|
+
|
50
|
+
def deferrable_adapter
|
51
|
+
@deferrable_adapter ||= DeferrableAdapter.new
|
52
|
+
end
|
53
|
+
|
54
|
+
def schedule_promise &block
|
55
|
+
EventMachine.defer block
|
56
|
+
end
|
57
|
+
|
58
|
+
def resolve_or_reject_child_as_needed
|
59
|
+
EventMachine.defer { super }
|
21
60
|
end
|
22
61
|
|
23
62
|
def generate_child_promise
|
24
63
|
ChildPromise.new driver: :em
|
25
64
|
end
|
26
65
|
|
66
|
+
def did_resolve value
|
67
|
+
notify_waiting
|
68
|
+
end
|
69
|
+
|
70
|
+
def did_reject value
|
71
|
+
notify_waiting
|
72
|
+
end
|
73
|
+
|
74
|
+
def notify_waiting
|
75
|
+
EventMachine.defer { @wait_cond.signal }
|
76
|
+
end
|
77
|
+
|
27
78
|
end
|
28
79
|
end
|
29
80
|
end
|