ntl-actor 0.3.1 → 0.4.0.pre1
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/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
|