ntl-actor 0.3.1 → 0.4.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/actor/actor.rb +7 -147
- data/lib/actor/address.rb +18 -0
- data/lib/actor/controls/actor.rb +27 -40
- data/lib/actor/controls/address.rb +48 -0
- data/lib/actor/controls/error.rb +17 -0
- data/lib/actor/controls/message/attribute.rb +17 -0
- data/lib/actor/controls/message.rb +23 -1
- data/lib/actor/controls/thread.rb +9 -0
- data/lib/actor/controls/uuid.rb +15 -0
- data/lib/actor/controls.rb +6 -10
- data/lib/actor/destructure.rb +23 -0
- data/lib/actor/{time_unit.rb → duration.rb} +1 -1
- data/lib/actor/messages.rb +15 -0
- data/lib/actor/messaging/message.rb +5 -0
- data/lib/actor/messaging/{writer → read}/substitute.rb +13 -10
- data/lib/actor/messaging/read.rb +50 -0
- data/lib/actor/messaging/write/substitute.rb +39 -0
- data/lib/actor/messaging/write.rb +26 -0
- data/lib/actor/module/build.rb +20 -0
- data/lib/actor/module/handle_macro.rb +39 -0
- data/lib/actor/module/start.rb +19 -0
- data/lib/actor/module.rb +73 -0
- data/lib/actor/router.rb +79 -0
- data/lib/actor/start.rb +46 -0
- data/lib/actor/stream.rb +36 -0
- data/lib/actor/substitutes/kernel.rb +23 -0
- data/lib/actor/substitutes/thread.rb +39 -0
- data/lib/actor/substitutes/thread_group.rb +26 -0
- data/lib/actor/supervisor.rb +46 -52
- data/lib/actor.rb +22 -14
- metadata +29 -29
- data/lib/actor/controls/statistics/elapsed_time/average.rb +0 -21
- data/lib/actor/controls/statistics/elapsed_time/maximum.rb +0 -21
- data/lib/actor/controls/statistics/elapsed_time/minimum.rb +0 -21
- data/lib/actor/controls/statistics/elapsed_time/standard_deviation.rb +0 -38
- data/lib/actor/controls/statistics/elapsed_time.rb +0 -15
- data/lib/actor/controls/statistics/timer.rb +0 -19
- data/lib/actor/controls/statistics.rb +0 -21
- data/lib/actor/controls/time/clock.rb +0 -31
- data/lib/actor/controls/time.rb +0 -24
- data/lib/actor/message.rb +0 -23
- data/lib/actor/messaging/address.rb +0 -40
- data/lib/actor/messaging/reader/substitute.rb +0 -40
- data/lib/actor/messaging/reader.rb +0 -31
- data/lib/actor/messaging/writer.rb +0 -26
- data/lib/actor/queue/assertions.rb +0 -13
- data/lib/actor/queue/reader.rb +0 -57
- data/lib/actor/queue.rb +0 -122
- data/lib/actor/statistics/copy.rb +0 -19
- data/lib/actor/statistics/timer.rb +0 -26
- data/lib/actor/statistics.rb +0 -75
- data/lib/actor/test_fixtures/parallel_iteration.rb +0 -143
- data/lib/actor/test_fixtures/sample_actor_status.rb +0 -45
- data/lib/actor/test_fixtures.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8390670d6cdb63d966590bc7456a583e424b21aa
|
4
|
+
data.tar.gz: 71bc7ef3d159c05ada78869eff267f6e683ff7a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9bc1d1dd129fa2d4275a3bb57a051826c7808f6d426c68cde2a3e336f1d70301ac2456729516dc7203e6a30a7ac8c17523e27d453270fd3f87867fca4acbcbf
|
7
|
+
data.tar.gz: 7164e075114eec599f0233c386f6bf77335e03edd140e51d28159d379e8b5280fc5181ffdce386f80ce6b6a37cb89076bbecedeee081a9fd4b84f72d1be879da
|
data/lib/actor/actor.rb
CHANGED
@@ -1,151 +1,11 @@
|
|
1
1
|
module Actor
|
2
|
+
# It is possible to `include Actor' in the top-level namespace in order to
|
3
|
+
# bring this library's constants into focus (i.e. reference them without any
|
4
|
+
# leading `Actor' reference to qualify them). The test suite does this; see
|
5
|
+
# tests/test_init.rb. In that case, we take care not to attach any Actor
|
6
|
+
# behavior onto Object. This is achieved by placing the implementation of
|
7
|
+
# Actor in Actor::Module
|
2
8
|
def self.included cls
|
3
|
-
cls.
|
4
|
-
extend Destructure
|
5
|
-
extend Spawn
|
6
|
-
extend Start
|
7
|
-
|
8
|
-
prepend UpdateStatistics
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
attr_accessor :actor_address
|
13
|
-
attr_accessor :actor_state
|
14
|
-
attr_writer :reader
|
15
|
-
|
16
|
-
def action
|
17
|
-
end
|
18
|
-
|
19
|
-
def actor_statistics
|
20
|
-
@actor_statistics ||= Statistics.new
|
21
|
-
end
|
22
|
-
|
23
|
-
def handle _
|
24
|
-
end
|
25
|
-
|
26
|
-
def handle_system_message message
|
27
|
-
case message
|
28
|
-
when Message::Pause then
|
29
|
-
self.actor_state = State::Paused
|
30
|
-
|
31
|
-
when Message::Resume then
|
32
|
-
self.actor_state = State::Running
|
33
|
-
|
34
|
-
when Message::Stop then
|
35
|
-
self.actor_state = State::Running
|
36
|
-
raise StopIteration
|
37
|
-
|
38
|
-
when Message::RecordStatus then
|
39
|
-
status = message.status
|
40
|
-
|
41
|
-
Statistics::Copy.(status, actor_statistics)
|
42
|
-
|
43
|
-
status.state = actor_state
|
44
|
-
status.actor_class = self.class.name
|
45
|
-
|
46
|
-
Messaging::Writer.(status, message.reply_address)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def reader
|
51
|
-
@reader ||= Reader::Substitute.new
|
52
|
-
end
|
53
|
-
|
54
|
-
def run_loop
|
55
|
-
loop do
|
56
|
-
while message = reader.(wait: actor_state == State::Paused)
|
57
|
-
handle message
|
58
|
-
|
59
|
-
if message.is_a? Message
|
60
|
-
handle_system_message message
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
action if actor_state == State::Running
|
65
|
-
|
66
|
-
Thread.pass
|
67
|
-
end
|
68
|
-
|
69
|
-
self.actor_state = State::Stopped
|
70
|
-
|
71
|
-
rescue => error
|
72
|
-
self.actor_state = State::Crashed
|
73
|
-
raise error
|
74
|
-
end
|
75
|
-
|
76
|
-
module Destructure
|
77
|
-
def destructure actor, address, thread, include: nil
|
78
|
-
return address if include.nil?
|
79
|
-
|
80
|
-
result = [address]
|
81
|
-
|
82
|
-
include.each do |variable_name|
|
83
|
-
value = binding.local_variable_get variable_name
|
84
|
-
|
85
|
-
result << value
|
86
|
-
end
|
87
|
-
|
88
|
-
return *result
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
module Spawn
|
93
|
-
def spawn *positional_arguments, include: nil, **keyword_arguments, &block
|
94
|
-
address = Messaging::Address.build
|
95
|
-
|
96
|
-
method = if respond_to? :build then :build else :new end
|
97
|
-
|
98
|
-
if keyword_arguments.empty?
|
99
|
-
instance = __send__ method, *positional_arguments, &block
|
100
|
-
else
|
101
|
-
instance = __send__ method, *positional_arguments, **keyword_arguments, &block
|
102
|
-
end
|
103
|
-
|
104
|
-
reader = Messaging::Reader.build address
|
105
|
-
|
106
|
-
instance.actor_address = address
|
107
|
-
instance.actor_state = State::Paused
|
108
|
-
instance.reader = reader
|
109
|
-
|
110
|
-
thread = ::Thread.new do
|
111
|
-
instance.run_loop
|
112
|
-
end
|
113
|
-
|
114
|
-
destructure instance, address, thread, include: include
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
module Start
|
119
|
-
def start *positional_arguments, include: nil, **keyword_arguments, &block
|
120
|
-
address, instance, thread = spawn(
|
121
|
-
*positional_arguments,
|
122
|
-
include: %i(actor thread),
|
123
|
-
**keyword_arguments,
|
124
|
-
&block
|
125
|
-
)
|
126
|
-
|
127
|
-
Messaging::Writer.(Message::Resume.new, address)
|
128
|
-
|
129
|
-
destructure instance, address, thread, include: include
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
module State
|
134
|
-
Crashed = :crashed
|
135
|
-
Paused = :paused
|
136
|
-
Running = :running
|
137
|
-
Stopped = :stopped
|
138
|
-
end
|
139
|
-
|
140
|
-
module UpdateStatistics
|
141
|
-
def action
|
142
|
-
actor_statistics.executing_action
|
143
|
-
|
144
|
-
result = super
|
145
|
-
|
146
|
-
actor_statistics.action_executed
|
147
|
-
|
148
|
-
result
|
149
|
-
end
|
9
|
+
cls.include Module unless cls == Object
|
150
10
|
end
|
151
11
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Actor
|
2
|
+
Address = Struct.new :stream, :uuid do
|
3
|
+
def self.build stream=nil
|
4
|
+
stream ||= Stream.new
|
5
|
+
|
6
|
+
uuid = SecureRandom.uuid
|
7
|
+
|
8
|
+
instance = new stream, uuid
|
9
|
+
instance
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Address
|
14
|
+
NoneClass = Class.new Address
|
15
|
+
|
16
|
+
None = NoneClass.build Stream::Null
|
17
|
+
end
|
18
|
+
end
|
data/lib/actor/controls/actor.rb
CHANGED
@@ -8,66 +8,53 @@ module Actor
|
|
8
8
|
class Example
|
9
9
|
include ::Actor
|
10
10
|
|
11
|
-
def
|
12
|
-
@
|
11
|
+
def initialize
|
12
|
+
@messages = []
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
@
|
15
|
+
handle Message::Example do |message|
|
16
|
+
@messages << message
|
17
|
+
nil
|
17
18
|
end
|
18
19
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def handled_messages
|
24
|
-
@handled_messages ||= []
|
20
|
+
def handled? message
|
21
|
+
@messages.include? message
|
25
22
|
end
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
expected_message ||= Message.example
|
25
|
+
class Continues
|
26
|
+
include ::Actor
|
30
27
|
|
31
|
-
|
28
|
+
def handle message
|
29
|
+
if message == Message.example
|
30
|
+
Message::Other.example
|
31
|
+
else
|
32
|
+
Message.example
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
|
-
class
|
37
|
-
|
38
|
-
super
|
39
|
-
raise Error, "Induced error"
|
40
|
-
end
|
37
|
+
class Stops
|
38
|
+
include ::Actor
|
41
39
|
|
42
|
-
|
43
|
-
|
40
|
+
handle :start do
|
41
|
+
@stopped = true
|
44
42
|
|
45
|
-
class StopsImmediately < Example
|
46
|
-
def action
|
47
|
-
super
|
48
43
|
raise StopIteration
|
49
44
|
end
|
50
|
-
end
|
51
45
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
def initialize req, opt=nil, keyreq:, key: nil, &block
|
56
|
-
@req, @opt, @keyreq, @key, @block = req, opt, keyreq, key, block
|
46
|
+
def stopped?
|
47
|
+
@stopped ? true : false
|
57
48
|
end
|
58
49
|
end
|
59
50
|
|
60
|
-
class
|
61
|
-
|
62
|
-
new req, keyreq: 'keyreq-value'
|
63
|
-
end
|
64
|
-
|
65
|
-
def argument_passed_in? value
|
66
|
-
req == value
|
67
|
-
end
|
51
|
+
class Singleton
|
52
|
+
include ::Actor
|
68
53
|
|
69
|
-
def
|
70
|
-
|
54
|
+
def self.define &block
|
55
|
+
cls = Class.new Singleton
|
56
|
+
cls.class_exec &block if block
|
57
|
+
cls.new
|
71
58
|
end
|
72
59
|
end
|
73
60
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Actor
|
2
|
+
module Controls
|
3
|
+
module Address
|
4
|
+
def self.example id_offset=nil, stream: nil
|
5
|
+
stream ||= Stream.new
|
6
|
+
|
7
|
+
uuid = UUID.example id_offset
|
8
|
+
|
9
|
+
::Actor::Address.new stream, uuid
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.pair id_offset=nil
|
13
|
+
stream = Stream.new
|
14
|
+
|
15
|
+
queue = Queue.new
|
16
|
+
stream.add_queue queue
|
17
|
+
|
18
|
+
address = example id_offset, stream: stream
|
19
|
+
|
20
|
+
return address, queue
|
21
|
+
end
|
22
|
+
|
23
|
+
module Actor
|
24
|
+
def self.example
|
25
|
+
Address.example 0
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module Supervisor
|
30
|
+
def self.example
|
31
|
+
Address.example 1
|
32
|
+
end
|
33
|
+
|
34
|
+
module Broadcast
|
35
|
+
def self.example
|
36
|
+
Address.example 2
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
module Router
|
42
|
+
def self.example
|
43
|
+
Address.example 3
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Actor
|
2
|
+
module Controls
|
3
|
+
module Error
|
4
|
+
def self.example
|
5
|
+
instance_eval <<~RUBY, '/path/to/some_file.rb', 1
|
6
|
+
def method_1; raise ::Actor::Controls::Error::Example; end
|
7
|
+
def method_2; method_1; end
|
8
|
+
method_2
|
9
|
+
RUBY
|
10
|
+
rescue Example => error
|
11
|
+
return error
|
12
|
+
end
|
13
|
+
|
14
|
+
Example = Class.new StandardError
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -2,7 +2,29 @@ module Actor
|
|
2
2
|
module Controls
|
3
3
|
module Message
|
4
4
|
def self.example
|
5
|
-
|
5
|
+
attribute = Attribute.example
|
6
|
+
|
7
|
+
Example.new attribute
|
8
|
+
end
|
9
|
+
|
10
|
+
module Other
|
11
|
+
def self.example
|
12
|
+
attribute = Attribute::Other.example
|
13
|
+
|
14
|
+
Example.new attribute
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
Example = Struct.new :some_attribute do
|
19
|
+
include Messaging::Message
|
20
|
+
end
|
21
|
+
|
22
|
+
module ActorStarted
|
23
|
+
def self.example
|
24
|
+
actor_address = Address::Actor.example
|
25
|
+
|
26
|
+
Messages::ActorStarted.new actor_address
|
27
|
+
end
|
6
28
|
end
|
7
29
|
end
|
8
30
|
end
|
data/lib/actor/controls.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
|
-
require 'actor/controls/
|
1
|
+
require 'actor/controls/address'
|
2
|
+
require 'actor/controls/error'
|
2
3
|
require 'actor/controls/message'
|
3
|
-
require 'actor/controls/
|
4
|
-
require 'actor/controls/
|
5
|
-
require 'actor/controls/
|
6
|
-
require 'actor/controls/
|
7
|
-
require 'actor/controls/statistics/elapsed_time/minimum'
|
8
|
-
require 'actor/controls/statistics/elapsed_time/standard_deviation'
|
9
|
-
require 'actor/controls/statistics/timer'
|
10
|
-
require 'actor/controls/time'
|
11
|
-
require 'actor/controls/time/clock'
|
4
|
+
require 'actor/controls/actor'
|
5
|
+
require 'actor/controls/message/attribute'
|
6
|
+
require 'actor/controls/uuid'
|
7
|
+
require 'actor/controls/thread'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Actor
|
2
|
+
module Destructure
|
3
|
+
def self.call primary_return_value, include=nil, **values
|
4
|
+
include = Array(include)
|
5
|
+
|
6
|
+
if include.empty?
|
7
|
+
primary_return_value
|
8
|
+
else
|
9
|
+
return_values = include.map do |return_value_name|
|
10
|
+
begin
|
11
|
+
values.fetch return_value_name
|
12
|
+
rescue KeyError
|
13
|
+
raise Error, "Invalid return value to include `#{return_value_name.inspect}'"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
return primary_return_value, *return_values
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Error = Class.new StandardError
|
22
|
+
end
|
23
|
+
end
|
@@ -1,8 +1,18 @@
|
|
1
1
|
module Actor
|
2
2
|
module Messaging
|
3
|
-
class
|
3
|
+
class Read
|
4
4
|
class Substitute
|
5
|
-
def call
|
5
|
+
def call wait: nil
|
6
|
+
message = messages.shift
|
7
|
+
|
8
|
+
if message.nil? and wait
|
9
|
+
raise WouldWait
|
10
|
+
end
|
11
|
+
|
12
|
+
message
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_message message
|
6
16
|
messages << message
|
7
17
|
end
|
8
18
|
|
@@ -10,15 +20,8 @@ module Actor
|
|
10
20
|
@messages ||= []
|
11
21
|
end
|
12
22
|
|
13
|
-
|
14
|
-
def written? &block
|
15
|
-
block ||= proc { true }
|
16
|
-
|
17
|
-
messages.any? &block
|
18
|
-
end
|
19
|
-
end
|
23
|
+
WouldWait = Class.new StandardError
|
20
24
|
|
21
|
-
# Eventide compatibility
|
22
25
|
singleton_class.send :alias_method, :build, :new
|
23
26
|
end
|
24
27
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Actor
|
2
|
+
module Messaging
|
3
|
+
class Read
|
4
|
+
attr_reader :queue
|
5
|
+
attr_reader :stream
|
6
|
+
|
7
|
+
def initialize queue, stream
|
8
|
+
@queue = queue
|
9
|
+
@stream = stream
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.build address
|
13
|
+
stream = address.stream
|
14
|
+
|
15
|
+
queue = Queue.new
|
16
|
+
stream.add_queue queue
|
17
|
+
|
18
|
+
instance = new queue, stream
|
19
|
+
instance
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.call address, wait: nil
|
23
|
+
instance = build address
|
24
|
+
instance.(wait: wait)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.configure receiver, address, attr_name: nil
|
28
|
+
attr_name ||= :reader
|
29
|
+
|
30
|
+
instance = build address
|
31
|
+
receiver.public_send "#{attr_name}=", instance
|
32
|
+
instance
|
33
|
+
end
|
34
|
+
|
35
|
+
def call wait: nil
|
36
|
+
if wait
|
37
|
+
queue.deq
|
38
|
+
else
|
39
|
+
non_block = true
|
40
|
+
|
41
|
+
begin
|
42
|
+
queue.deq non_block
|
43
|
+
rescue ThreadError
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Actor
|
2
|
+
module Messaging
|
3
|
+
class Write
|
4
|
+
class Substitute
|
5
|
+
attr_reader :records
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@records = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def call message, address
|
12
|
+
record = Record.new message, address
|
13
|
+
|
14
|
+
records << record
|
15
|
+
|
16
|
+
record
|
17
|
+
end
|
18
|
+
|
19
|
+
Record = Struct.new :message, :address
|
20
|
+
|
21
|
+
singleton_class.send :alias_method, :build, :new
|
22
|
+
|
23
|
+
module Assertions
|
24
|
+
def written? message=nil, &block
|
25
|
+
if message.nil?
|
26
|
+
block ||= proc { true }
|
27
|
+
else
|
28
|
+
block ||= proc { |msg| msg == message }
|
29
|
+
end
|
30
|
+
|
31
|
+
records.any? do |record|
|
32
|
+
block.(record.message, record.address)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Actor
|
2
|
+
module Messaging
|
3
|
+
class Write
|
4
|
+
def self.call message, address
|
5
|
+
instance = new
|
6
|
+
instance.(message, address)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.configure receiver, attr_name: nil
|
10
|
+
attr_name ||= :writer
|
11
|
+
|
12
|
+
instance = new
|
13
|
+
receiver.public_send "#{attr_name}=", instance
|
14
|
+
instance
|
15
|
+
end
|
16
|
+
|
17
|
+
def call message, address
|
18
|
+
stream = address.stream
|
19
|
+
|
20
|
+
stream.write message
|
21
|
+
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Actor
|
2
|
+
module Module
|
3
|
+
module Build
|
4
|
+
def build address, *positional_arguments, **keyword_arguments, &block
|
5
|
+
if keyword_arguments.empty?
|
6
|
+
instance = new *positional_arguments, &block
|
7
|
+
else
|
8
|
+
instance = new *positional_arguments, **keyword_arguments, &block
|
9
|
+
end
|
10
|
+
|
11
|
+
instance.reader = Messaging::Read.build address
|
12
|
+
instance.writer = Messaging::Write.new
|
13
|
+
|
14
|
+
instance.configure
|
15
|
+
|
16
|
+
instance
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|