ntl-actor 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 47b2908a5c8c0845acf09f5f4f7a75e89c913d55
4
- data.tar.gz: a90ae411a5f3bc54ee2e169067cf6d3c5c0dcadf
3
+ metadata.gz: 6a248085a59139b5a654ffd3c4d88a125c409847
4
+ data.tar.gz: 0a95b14dc7bee4ce4ffb259c4058baedf2a59be1
5
5
  SHA512:
6
- metadata.gz: d6321566f603c6884202bc129e3435bba0a8f91fd8ae8c06c3a6db16dbf6487b1f43ab82a278a61276200c755cacd0ba23b67a6252ec6d6e80f52422f5aee4a2
7
- data.tar.gz: 250ba0a32174e3311debcc64bdf92d63bdddb40df5546657403453879992b315a7493e787400a06a125020f72d7826d0a96ad60cd3d52dd34581a3ab2eb02c48
6
+ metadata.gz: 21bed49350bde9295a5d5380b2d80a6c4a5d4ef2c8241e3b5ef4795d1c24c866116be5695339cd639bb44a7ef850aa6d1dc9fc26b67d0f955865d44f005d14fb
7
+ data.tar.gz: 9fc7de957667da0179a58e37ff7aaa4d72991839cbbaec75b01ea0b34f52ab42187fde4cdc678b920e8b5b55209d54db61e259c3a7735252dac19292604a682e
data/lib/actor.rb CHANGED
@@ -18,4 +18,7 @@ require 'actor/messaging/writer/substitute'
18
18
 
19
19
  require 'actor/message'
20
20
 
21
+ require 'actor/time_unit'
22
+
21
23
  require 'actor/actor'
24
+ require 'actor/supervisor'
data/lib/actor/actor.rb CHANGED
@@ -41,8 +41,9 @@ module Actor
41
41
  Statistics::Copy.(status, actor_statistics)
42
42
 
43
43
  status.state = actor_state
44
+ status.actor_class = self.class.name
44
45
 
45
- Messaging::Writer.write status, message.reply_address
46
+ Messaging::Writer.(status, message.reply_address)
46
47
  end
47
48
  end
48
49
 
@@ -52,7 +53,7 @@ module Actor
52
53
 
53
54
  def run_loop
54
55
  loop do
55
- while message = reader.read(wait: actor_state == State::Paused)
56
+ while message = reader.(wait: actor_state == State::Paused)
56
57
  handle message
57
58
 
58
59
  if message.is_a? Message
@@ -90,7 +91,7 @@ module Actor
90
91
 
91
92
  module Spawn
92
93
  def spawn *positional_arguments, include: nil, **keyword_arguments, &block
93
- address = Messaging::Address.get
94
+ address = Messaging::Address.build
94
95
 
95
96
  method = if respond_to? :build then :build else :new end
96
97
 
@@ -123,10 +124,7 @@ module Actor
123
124
  &block
124
125
  )
125
126
 
126
- Messaging::Writer.write(
127
- Message::Resume.new,
128
- address
129
- )
127
+ Messaging::Writer.(Message::Resume.new, address)
130
128
 
131
129
  destructure instance, address, thread, include: include
132
130
  end
@@ -1,4 +1,5 @@
1
1
  require 'actor/controls/actor'
2
+ require 'actor/controls/message'
2
3
  require 'actor/controls/statistics'
3
4
  require 'actor/controls/statistics/elapsed_time'
4
5
  require 'actor/controls/statistics/elapsed_time/average'
@@ -7,6 +7,68 @@ module Actor
7
7
 
8
8
  class Example
9
9
  include ::Actor
10
+
11
+ def action
12
+ @acted = true
13
+ end
14
+
15
+ def action_executed?
16
+ @acted == true
17
+ end
18
+
19
+ def handle message
20
+ handled_messages << message
21
+ end
22
+
23
+ def handled_messages
24
+ @handled_messages ||= []
25
+ end
26
+
27
+ module Assertions
28
+ def handled_message? expected_message
29
+ expected_message ||= Message.example
30
+
31
+ @handled_messages.include? expected_message
32
+ end
33
+ end
34
+ end
35
+
36
+ class CrashesImmediately < Example
37
+ def action
38
+ super
39
+ raise Error, "Induced error"
40
+ end
41
+
42
+ Error = Class.new StandardError
43
+ end
44
+
45
+ class StopsImmediately < Example
46
+ def action
47
+ super
48
+ raise StopIteration
49
+ end
50
+ end
51
+
52
+ class ConstructorArguments < StopsImmediately
53
+ attr_reader :req, :opt, :keyreq, :key, :block
54
+
55
+ def initialize req, opt=nil, keyreq:, key: nil, &block
56
+ @req, @opt, @keyreq, @key, @block = req, opt, keyreq, key, block
57
+ end
58
+ end
59
+
60
+ class FactoryMethod < ConstructorArguments
61
+ def self.build req
62
+ new req, keyreq: 'keyreq-value'
63
+ end
64
+
65
+ def argument_passed_in? value
66
+ req == value
67
+ end
68
+
69
+ def constructed_by_factory_method?
70
+ keyreq == 'keyreq-value'
71
+ end
10
72
  end
11
73
  end
12
74
  end
@@ -0,0 +1,9 @@
1
+ module Actor
2
+ module Controls
3
+ module Message
4
+ def self.example
5
+ 'some-message'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -9,7 +9,7 @@ module Actor
9
9
  @queue = queue
10
10
  end
11
11
 
12
- def self.get
12
+ def self.build
13
13
  id = SecureRandom.uuid
14
14
  queue = Queue.new
15
15
 
@@ -15,7 +15,7 @@ module Actor
15
15
  new queue_reader
16
16
  end
17
17
 
18
- def read wait: nil
18
+ def call wait: nil
19
19
  queue_reader.read wait: wait
20
20
  end
21
21
 
@@ -4,7 +4,7 @@ module Actor
4
4
  class Substitute
5
5
  attr_accessor :stopped
6
6
 
7
- def read wait: nil
7
+ def call wait: nil
8
8
  message = messages.shift
9
9
 
10
10
  return message if message
@@ -13,12 +13,12 @@ module Actor
13
13
  new queue
14
14
  end
15
15
 
16
- def self.write message, address
16
+ def self.call message, address
17
17
  instance = build address
18
- instance.write message
18
+ instance.(message)
19
19
  end
20
20
 
21
- def write message
21
+ def call message
22
22
  queue.write message
23
23
  end
24
24
  end
@@ -2,7 +2,7 @@ module Actor
2
2
  module Messaging
3
3
  class Writer
4
4
  class Substitute
5
- def write message
5
+ def call message
6
6
  messages << message
7
7
  end
8
8
 
@@ -0,0 +1,77 @@
1
+ module Actor
2
+ class Supervisor
3
+ attr_reader :actors
4
+ attr_writer :exception_notifier
5
+
6
+ def initialize
7
+ @actors = Set.new
8
+ end
9
+
10
+ def add address, thread
11
+ actor = Actor.new address, thread
12
+
13
+ actors << actor
14
+
15
+ actor
16
+ end
17
+
18
+ def remove address
19
+ actors.delete_if do |actor|
20
+ actor.address == address
21
+ end
22
+ end
23
+
24
+ def broadcast message
25
+ addresses = actors.map &:address
26
+
27
+ addresses.each do |address|
28
+ Messaging::Writer.(message, address)
29
+ end
30
+ end
31
+
32
+ def pause
33
+ broadcast Message::Pause.new
34
+ end
35
+
36
+ def resume
37
+ broadcast Message::Resume.new
38
+ end
39
+
40
+ def stop
41
+ broadcast Message::Stop.new
42
+ end
43
+
44
+ def start &supplementary_action
45
+ loop do
46
+ supplementary_action.() if supplementary_action
47
+
48
+ actors.delete_if do |actor|
49
+ thread = actor.thread
50
+ thread.join TimeUnit.millisecond
51
+ end
52
+
53
+ break if actors.empty?
54
+
55
+ Thread.pass
56
+ end
57
+
58
+ rescue => error
59
+ exception_notifier.(error)
60
+ raise error
61
+ end
62
+
63
+ def exception_notifier
64
+ @exception_notifier ||= proc { }
65
+ end
66
+
67
+ Actor = Struct.new :address, :thread
68
+
69
+ module Assertions
70
+ def actor? actor_address
71
+ actors.any? do |actor|
72
+ actor.address == actor_address
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -14,7 +14,7 @@ module Actor
14
14
  end
15
15
 
16
16
  def self.call prose, address:, test:
17
- reply_address = Messaging::Address.get
17
+ reply_address = Messaging::Address.build
18
18
  reader = Messaging::Reader.build reply_address
19
19
 
20
20
  writer = Messaging::Writer.build address
@@ -24,13 +24,13 @@ module Actor
24
24
  end
25
25
 
26
26
  def call test_prose, &block
27
- writer.write record_status_message
27
+ writer.(record_status_message)
28
28
 
29
- status_0 = reader.read wait: true
29
+ status_0 = reader.(wait: true)
30
30
 
31
- writer.write record_status_message
31
+ writer.(record_status_message)
32
32
 
33
- status_1 = reader.read wait: true
33
+ status_1 = reader.(wait: true)
34
34
 
35
35
  test test_prose do
36
36
  block.(status_1, status_0)
@@ -0,0 +1,7 @@
1
+ module Actor
2
+ module TimeUnit
3
+ def self.millisecond
4
+ 0.001
5
+ end
6
+ end
7
+ end
metadata CHANGED
@@ -1,17 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ntl-actor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan Ladd
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2016-08-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description: Implementation of actor pattern for ruby designed for simplicity and
14
- frugality
13
+ description: Implementation of actor pattern for ruby designed for simplicity and frugality
15
14
  email: nathanladd+github@gmail.com
16
15
  executables: []
17
16
  extensions: []
@@ -21,6 +20,7 @@ files:
21
20
  - lib/actor/actor.rb
22
21
  - lib/actor/controls.rb
23
22
  - lib/actor/controls/actor.rb
23
+ - lib/actor/controls/message.rb
24
24
  - lib/actor/controls/statistics.rb
25
25
  - lib/actor/controls/statistics/elapsed_time.rb
26
26
  - lib/actor/controls/statistics/elapsed_time/average.rb
@@ -42,14 +42,16 @@ files:
42
42
  - lib/actor/statistics.rb
43
43
  - lib/actor/statistics/copy.rb
44
44
  - lib/actor/statistics/timer.rb
45
+ - lib/actor/supervisor.rb
45
46
  - lib/actor/test_fixtures.rb
46
47
  - lib/actor/test_fixtures/parallel_iteration.rb
47
48
  - lib/actor/test_fixtures/sample_actor_status.rb
49
+ - lib/actor/time_unit.rb
48
50
  homepage: https://github.com/ntl/actor
49
51
  licenses:
50
52
  - MIT
51
53
  metadata: {}
52
- post_install_message:
54
+ post_install_message:
53
55
  rdoc_options: []
54
56
  require_paths:
55
57
  - lib
@@ -64,9 +66,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
66
  - !ruby/object:Gem::Version
65
67
  version: '0'
66
68
  requirements: []
67
- rubyforge_project:
68
- rubygems_version: 2.6.6
69
- signing_key:
69
+ rubyforge_project:
70
+ rubygems_version: 2.6.4
71
+ signing_key:
70
72
  specification_version: 4
71
73
  summary: Implementation of actor pattern for ruby
72
74
  test_files: []