tribe 0.0.6 → 0.0.7
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.
- data/Gemfile.lock +1 -1
- data/README.md +7 -8
- data/lib/tribe/actable.rb +80 -0
- data/lib/tribe/actor.rb +2 -81
- data/lib/tribe/mailbox.rb +11 -27
- data/lib/tribe/version.rb +1 -1
- data/lib/tribe.rb +4 -3
- data/tribe.gemspec +3 -3
- metadata +8 -5
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# Tribe
|
2
2
|
|
3
|
-
Tribe is a Ruby gem that implements event driven actors.
|
4
|
-
Actors are
|
3
|
+
Tribe is a Ruby gem that implements event driven [actors] (http://en.wikipedia.org/wiki/Actor_model "actors").
|
4
|
+
Actors are lightweight concurrent objects that use asynchronous message passing for communication.
|
5
|
+
Tribe focuses on high performance, low latency, an easy to use API, and flexibility.
|
6
|
+
It is built on top of the [Workers] (https://github.com/chadrem/workers "Workers") gem, which allows it to support many actors (millions should be possible).
|
7
|
+
Actors can use a shared thread pool (default) or dedicted threads.
|
5
8
|
|
6
9
|
## Installation
|
7
10
|
|
@@ -51,7 +54,7 @@ Or install it yourself as:
|
|
51
54
|
MyActor.new(:name => "my_actor_#{i}")
|
52
55
|
end
|
53
56
|
|
54
|
-
# Send an event to each actors. Find each actor using the registry.
|
57
|
+
# Send an event to each actors. Find each actor using the global registry.
|
55
58
|
100.times do |i|
|
56
59
|
actor = Tribe.registry["my_actor_#{i}"]
|
57
60
|
actor.enqueue(:my_custom, 'hello world')
|
@@ -64,7 +67,7 @@ Or install it yourself as:
|
|
64
67
|
end
|
65
68
|
|
66
69
|
### Implementation notes
|
67
|
-
Because actors use a shared thread pool, it is important that they don't block for long periods of time.
|
70
|
+
Because actors use a shared thread pool, it is important that they don't block for long periods of time (short periods are fine).
|
68
71
|
Actors that block for long periods of time should use a dedicated thread (:dedicated => true or subclass from Tribe::DedicatedActor).
|
69
72
|
|
70
73
|
## Registries
|
@@ -104,7 +107,3 @@ In general you shouldn't have to create your own since there is a global one (Tr
|
|
104
107
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
105
108
|
4. Push to the branch (`git push origin my-new-feature`)
|
106
109
|
5. Create new Pull Request
|
107
|
-
|
108
|
-
## Copyright
|
109
|
-
|
110
|
-
Copyright (c) 2012 Chad Remesch. See LICENSE.txt for further details.
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Tribe
|
2
|
+
module Actable
|
3
|
+
include Workers::Helpers
|
4
|
+
|
5
|
+
def init_actable(options = {})
|
6
|
+
@logger = Workers::LogProxy.new(options[:logger])
|
7
|
+
@dedicated = options[:dedicated] || false
|
8
|
+
@mailbox = options[:mailbox] || Tribe::Mailbox.new
|
9
|
+
@registry = options[:registry] || Tribe.registry
|
10
|
+
@name = options[:name]
|
11
|
+
@pool = @dedicated ? Workers::Pool.new(:size => 1) : (options[:pool] || Workers.pool)
|
12
|
+
@alive = true
|
13
|
+
|
14
|
+
@registry.register(self)
|
15
|
+
end
|
16
|
+
|
17
|
+
def enqueue(command, data = nil)
|
18
|
+
return false unless alive?
|
19
|
+
|
20
|
+
@mailbox.push(Workers::Event.new(command, data)) do
|
21
|
+
@pool.perform { process_events }
|
22
|
+
end
|
23
|
+
|
24
|
+
return true
|
25
|
+
end
|
26
|
+
|
27
|
+
def alive?
|
28
|
+
@mailbox.synchronize { return @alive }
|
29
|
+
end
|
30
|
+
|
31
|
+
def name
|
32
|
+
return @name
|
33
|
+
end
|
34
|
+
|
35
|
+
def identifier
|
36
|
+
return @name ? "#{object_id}:#{@name}" : object_id
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def process_events
|
42
|
+
while (event = @mailbox.shift)
|
43
|
+
case event.command
|
44
|
+
when :shutdown
|
45
|
+
shutdown_handler(event)
|
46
|
+
@pool.shutdown if @dedicated
|
47
|
+
@mailbox.synchronize { @alive = false }
|
48
|
+
else
|
49
|
+
process_event(event)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
rescue Exception => e
|
54
|
+
@alive = false
|
55
|
+
exception_handler(e)
|
56
|
+
ensure
|
57
|
+
@mailbox.release do
|
58
|
+
@pool.perform { process_events }
|
59
|
+
end
|
60
|
+
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# Subclass and override the below methods.
|
66
|
+
#
|
67
|
+
|
68
|
+
def process_event(event)
|
69
|
+
puts "Actor (#{identifier}) processing event (#{event.inspect}) using thread (#{Thread.current.object_id})."
|
70
|
+
end
|
71
|
+
|
72
|
+
def exception_handler(e)
|
73
|
+
puts concat_e("Actor (#{identifier}) died.", e)
|
74
|
+
end
|
75
|
+
|
76
|
+
def shutdown_handler(event)
|
77
|
+
puts "Actor (#{identifier}) is shutting down."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/tribe/actor.rb
CHANGED
@@ -1,88 +1,9 @@
|
|
1
1
|
module Tribe
|
2
2
|
class Actor
|
3
|
-
include
|
3
|
+
include Tribe::Actable
|
4
4
|
|
5
5
|
def initialize(options = {})
|
6
|
-
|
7
|
-
@dedicated = options[:dedicated] || false
|
8
|
-
@mailbox = options[:mailbox] || Tribe::Mailbox.new
|
9
|
-
@registry = options[:registry] || Tribe.registry
|
10
|
-
@name = options[:name]
|
11
|
-
@pool = @dedicated ? Workers::Pool.new(:size => 1) : (options[:pool] || Workers.pool)
|
12
|
-
@alive = true
|
13
|
-
|
14
|
-
@registry.register(self)
|
15
|
-
end
|
16
|
-
|
17
|
-
def enqueue(command, data = nil)
|
18
|
-
return false unless alive?
|
19
|
-
|
20
|
-
@mailbox.push(Workers::Event.new(command, data))
|
21
|
-
|
22
|
-
@pool.perform do
|
23
|
-
process_events
|
24
|
-
end
|
25
|
-
|
26
|
-
return true
|
27
|
-
end
|
28
|
-
|
29
|
-
def alive?
|
30
|
-
@mailbox.synchronize do
|
31
|
-
return @alive
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def name
|
36
|
-
return @name
|
37
|
-
end
|
38
|
-
|
39
|
-
def identifier
|
40
|
-
return @name ? "#{object_id}:#{@name}" : object_id
|
41
|
-
end
|
42
|
-
|
43
|
-
private
|
44
|
-
|
45
|
-
def process_events
|
46
|
-
while (event = @mailbox.shift)
|
47
|
-
case event.command
|
48
|
-
when :shutdown
|
49
|
-
shutdown_handler(event)
|
50
|
-
@pool.shutdown if @dedicated
|
51
|
-
@mailbox.synchronize do
|
52
|
-
@alive = false
|
53
|
-
end
|
54
|
-
else
|
55
|
-
process_event(event)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
rescue Exception => e
|
60
|
-
@alive = false
|
61
|
-
exception_handler(e)
|
62
|
-
ensure
|
63
|
-
@mailbox.release do
|
64
|
-
@pool.perform do
|
65
|
-
process_events
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
return nil
|
70
|
-
end
|
71
|
-
|
72
|
-
#
|
73
|
-
# Subclass and override the below methods.
|
74
|
-
#
|
75
|
-
|
76
|
-
def process_event(event)
|
77
|
-
puts "Actor (#{identifier}) processing event (#{event.inspect}) using thread (#{Thread.current.object_id})."
|
78
|
-
end
|
79
|
-
|
80
|
-
def exception_handler(e)
|
81
|
-
puts concat_e("Actor (#{identifier}) died.", e)
|
82
|
-
end
|
83
|
-
|
84
|
-
def shutdown_handler(event)
|
85
|
-
puts "Actor (#{identifier}) is shutting down."
|
6
|
+
init_actable(options)
|
86
7
|
end
|
87
8
|
end
|
88
9
|
end
|
data/lib/tribe/mailbox.rb
CHANGED
@@ -5,10 +5,13 @@ module Tribe
|
|
5
5
|
@mutex = Mutex.new
|
6
6
|
end
|
7
7
|
|
8
|
-
def push(event)
|
8
|
+
def push(event, &block)
|
9
9
|
@mutex.synchronize do
|
10
10
|
@messages.push(event)
|
11
|
+
block.call unless @current_thread
|
11
12
|
end
|
13
|
+
|
14
|
+
return nil
|
12
15
|
end
|
13
16
|
|
14
17
|
def shift
|
@@ -17,44 +20,25 @@ module Tribe
|
|
17
20
|
|
18
21
|
@current_thread = Thread.current unless @current_thread
|
19
22
|
|
20
|
-
@messages.shift
|
23
|
+
return @messages.shift
|
21
24
|
end
|
22
25
|
end
|
23
26
|
|
24
|
-
def release(&
|
27
|
+
def release(&block)
|
25
28
|
@mutex.synchronize do
|
26
29
|
@current_thread = nil
|
27
|
-
|
28
|
-
if requeue_block && @messages.length > 0
|
29
|
-
requeue_block.call
|
30
|
-
end
|
30
|
+
block.call if block && @messages.length > 0
|
31
31
|
end
|
32
|
+
|
33
|
+
return nil
|
32
34
|
end
|
33
35
|
|
34
36
|
def synchronize(&block)
|
35
37
|
@mutex.synchronize do
|
36
38
|
block.call
|
37
39
|
end
|
38
|
-
end
|
39
|
-
|
40
|
-
# def obtain
|
41
|
-
# @mutex.synchronize do
|
42
|
-
# return false if @current_thread && @current_thread != Thread.current
|
43
40
|
|
44
|
-
|
45
|
-
|
46
|
-
# return true
|
47
|
-
# end
|
48
|
-
# end
|
49
|
-
|
50
|
-
# def release
|
51
|
-
# @mutex.synchronize do
|
52
|
-
# return false unless @current_thread && @current_thread == Thread.current
|
53
|
-
|
54
|
-
# @current_thread = nil
|
55
|
-
|
56
|
-
# return true
|
57
|
-
# end
|
58
|
-
# end
|
41
|
+
return nil
|
42
|
+
end
|
59
43
|
end
|
60
44
|
end
|
data/lib/tribe/version.rb
CHANGED
data/lib/tribe.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'workers'
|
2
2
|
|
3
3
|
require 'tribe/mailbox'
|
4
|
+
require 'tribe/actable'
|
4
5
|
require 'tribe/actor'
|
5
6
|
require 'tribe/dedicated_actor'
|
6
7
|
require 'tribe/registry'
|
@@ -8,12 +9,12 @@ require 'tribe/registry'
|
|
8
9
|
module Tribe
|
9
10
|
def self.registry
|
10
11
|
return @registry ||= Tribe::Registry.new
|
11
|
-
end
|
12
|
+
end
|
12
13
|
|
13
14
|
def self.registry=(val)
|
14
15
|
@registry.dispose if @registry
|
15
|
-
@registry = val
|
16
|
-
end
|
16
|
+
@registry = val
|
17
|
+
end
|
17
18
|
end
|
18
19
|
|
19
20
|
# Force initialization of defaults.
|
data/tribe.gemspec
CHANGED
@@ -4,9 +4,9 @@ require File.expand_path('../lib/tribe/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Chad Remesch"]
|
6
6
|
gem.email = ["chad@remesch.com"]
|
7
|
-
gem.description = %q{
|
8
|
-
gem.summary = %q{
|
9
|
-
gem.homepage = ""
|
7
|
+
gem.description = %q{Tribe is a Ruby gem that implements event driven actors.}
|
8
|
+
gem.summary = %q{Actors are lightweight concurrent objects that use asynchronous message passing for communication. Tribe focuses on high performance, low latency, an easy to use API, and flexibility.}
|
9
|
+
gem.homepage = "https://github.com/chadrem/tribe"
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
12
12
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tribe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
12
|
+
date: 2013-01-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: workers
|
@@ -27,7 +27,7 @@ dependencies:
|
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 0.0.6
|
30
|
-
description:
|
30
|
+
description: Tribe is a Ruby gem that implements event driven actors.
|
31
31
|
email:
|
32
32
|
- chad@remesch.com
|
33
33
|
executables: []
|
@@ -41,13 +41,14 @@ files:
|
|
41
41
|
- README.md
|
42
42
|
- Rakefile
|
43
43
|
- lib/tribe.rb
|
44
|
+
- lib/tribe/actable.rb
|
44
45
|
- lib/tribe/actor.rb
|
45
46
|
- lib/tribe/dedicated_actor.rb
|
46
47
|
- lib/tribe/mailbox.rb
|
47
48
|
- lib/tribe/registry.rb
|
48
49
|
- lib/tribe/version.rb
|
49
50
|
- tribe.gemspec
|
50
|
-
homepage:
|
51
|
+
homepage: https://github.com/chadrem/tribe
|
51
52
|
licenses: []
|
52
53
|
post_install_message:
|
53
54
|
rdoc_options: []
|
@@ -70,5 +71,7 @@ rubyforge_project:
|
|
70
71
|
rubygems_version: 1.8.24
|
71
72
|
signing_key:
|
72
73
|
specification_version: 3
|
73
|
-
summary:
|
74
|
+
summary: Actors are lightweight concurrent objects that use asynchronous message passing
|
75
|
+
for communication. Tribe focuses on high performance, low latency, an easy to use
|
76
|
+
API, and flexibility.
|
74
77
|
test_files: []
|