mr_darcy 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|