tribe 0.0.4 → 0.0.5
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/README.md +82 -1
- data/Rakefile +4 -97
- data/lib/tribe/version.rb +1 -1
- data/tribe.gemspec +1 -1
- metadata +2 -8
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Tribe
|
2
2
|
|
3
|
-
|
3
|
+
Tribe is a Ruby gem that implements event driven actors.
|
4
|
+
Actors are light weight concurrent objects that use asynchronous message passing for communication.
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -16,6 +17,86 @@ Or install it yourself as:
|
|
16
17
|
|
17
18
|
$ gem install tribe
|
18
19
|
|
20
|
+
## Actors
|
21
|
+
|
22
|
+
# Create your custom actor class.
|
23
|
+
class MyActor < Tribe::Actor
|
24
|
+
private
|
25
|
+
def initialize(options = {})
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def process_event(event)
|
30
|
+
case event.command
|
31
|
+
when :my_custom
|
32
|
+
my_custom_handler(event)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def my_custom_handler(event)
|
37
|
+
puts "Received a custom event (#{event.inspect})"
|
38
|
+
end
|
39
|
+
|
40
|
+
def exception_handler(e)
|
41
|
+
puts concat_e("MyActor (#{identifier}) died.", e)
|
42
|
+
end
|
43
|
+
|
44
|
+
def shutdown_handler(event)
|
45
|
+
puts "MyActor (#{identifier}) is shutting down. Put cleanup code here."
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Create some named actors.
|
50
|
+
100.times do |i|
|
51
|
+
MyActor.new(:name => "my_actor_#{i}")
|
52
|
+
end
|
53
|
+
|
54
|
+
# Send an event to each actors. Find each actor using the registry.
|
55
|
+
100.times do |i|
|
56
|
+
actor = Tribe.registry["my_actor_#{i}"]
|
57
|
+
actor.enqueue(:my_custom, 'hello world')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Shutdown the actors.
|
61
|
+
100.times do |i|
|
62
|
+
actor = Tribe.registry["my_actor_#{i}"]
|
63
|
+
actor.enqueue(:shutdown)
|
64
|
+
end
|
65
|
+
|
66
|
+
### Implementation notes
|
67
|
+
Because actors use a shared thread pool, it is important that they don't block for long periods of time.
|
68
|
+
Actors that block for long periods of time should use a dedicated thread (:dedicated => true or subclass from Tribe::DedicatedActor).
|
69
|
+
|
70
|
+
## Registries
|
71
|
+
|
72
|
+
Registries hold references to named actors.
|
73
|
+
In general you shouldn't have to create your own since there is a global one (Tribe.registry).
|
74
|
+
|
75
|
+
## Options (defaults below):
|
76
|
+
|
77
|
+
actor = Tribe::Actor.new(
|
78
|
+
:logger => nil, # Ruby logger instance.
|
79
|
+
:dedicated => false, # If true, the actor runs with a worker pool that has one thread.
|
80
|
+
:pool => Workers.pool, # The workers pool used to execute events.
|
81
|
+
:mailbox => Tribe::Mailbox.new, # The mailbox used to receive events.
|
82
|
+
:registry => Tribe.registry, # The registry used to store a reference to the actor if it has a name.
|
83
|
+
:name => nil # The name of the actor (must be unique in the registry).
|
84
|
+
)
|
85
|
+
|
86
|
+
actor = Tribe::DedicatedActor.new(
|
87
|
+
:logger => nil, # Ruby logger instance.
|
88
|
+
:mailbox => Tribe::Mailbox.new, # The mailbox used to receive events.
|
89
|
+
:registry => Tribe.registry, # The registry used to store a reference to the actor if it has a name.
|
90
|
+
:name => nil # The name of the actor (must be unique in the registry).
|
91
|
+
)
|
92
|
+
|
93
|
+
## TODO - missing features
|
94
|
+
|
95
|
+
- Futures.
|
96
|
+
- Workers::Timer integration.
|
97
|
+
- Supervisors.
|
98
|
+
- Linking.
|
99
|
+
|
19
100
|
## Contributing
|
20
101
|
|
21
102
|
1. Fork it
|
data/Rakefile
CHANGED
@@ -1,106 +1,13 @@
|
|
1
|
-
|
2
|
-
require 'bundler/gem_tasks'
|
3
|
-
require 'benchmark'
|
1
|
+
require "bundler/gem_tasks"
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts(e.message)
|
9
|
-
$stderr.puts("Run `bundle install` to install missing gems")
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
|
13
|
-
task :environment do
|
3
|
+
desc 'Start an IRB console with Workers loaded'
|
4
|
+
task :console do
|
14
5
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
15
|
-
require 'tribe'
|
16
|
-
end
|
17
6
|
|
18
|
-
|
19
|
-
task :console => :environment do
|
7
|
+
require 'tribe'
|
20
8
|
require 'irb'
|
21
9
|
|
22
10
|
ARGV.clear
|
23
11
|
|
24
12
|
IRB.start
|
25
13
|
end
|
26
|
-
|
27
|
-
desc 'Demo mode (temporary)'
|
28
|
-
task :demo => :environment do
|
29
|
-
$demo_queue = Queue.new
|
30
|
-
$demo_mutex = Mutex.new
|
31
|
-
|
32
|
-
def locked_puts(msg)
|
33
|
-
$demo_mutex.synchronize { puts msg }
|
34
|
-
end
|
35
|
-
|
36
|
-
DEMO_ACTOR_COUNT = 100
|
37
|
-
DEMO_MSG_COUNT = 3000
|
38
|
-
|
39
|
-
class MyActor < Tribe::Actor
|
40
|
-
|
41
|
-
def pre_init
|
42
|
-
reset_count
|
43
|
-
end
|
44
|
-
|
45
|
-
def increment
|
46
|
-
@count += 1
|
47
|
-
|
48
|
-
if @count >= DEMO_MSG_COUNT
|
49
|
-
locked_puts("#{@name} done.")
|
50
|
-
$demo_queue.push(@name)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def reset_count
|
55
|
-
@count = 0
|
56
|
-
end
|
57
|
-
|
58
|
-
def go(friend_name)
|
59
|
-
friend = Tribe.registry[friend_name]
|
60
|
-
|
61
|
-
DEMO_MSG_COUNT.times do
|
62
|
-
friend.increment!
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def tribe_demo
|
68
|
-
actors = []
|
69
|
-
|
70
|
-
locked_puts('Create actors...')
|
71
|
-
(0...DEMO_ACTOR_COUNT).each do |i|
|
72
|
-
name = i.to_s
|
73
|
-
actor = Tribe.registry[name] || MyActor.new(:name => name)
|
74
|
-
actors.push(actor)
|
75
|
-
locked_puts(name)
|
76
|
-
end
|
77
|
-
|
78
|
-
locked_puts('Resetting...')
|
79
|
-
actors.each do |actor|
|
80
|
-
actor.reset_count!
|
81
|
-
end
|
82
|
-
|
83
|
-
locked_puts('Go...')
|
84
|
-
actors.each do |actor|
|
85
|
-
friend = actor.name.to_i
|
86
|
-
friend += 1
|
87
|
-
friend = 0 if friend == DEMO_ACTOR_COUNT
|
88
|
-
friend = friend.to_s
|
89
|
-
|
90
|
-
locked_puts("pair: #{actor.name}, #{friend}")
|
91
|
-
actor.go!(friend)
|
92
|
-
end
|
93
|
-
|
94
|
-
locked_puts('Benchmark...')
|
95
|
-
result = Benchmark.realtime do
|
96
|
-
DEMO_ACTOR_COUNT.times do
|
97
|
-
$demo_queue.pop
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
nil
|
102
|
-
end
|
103
|
-
|
104
|
-
tribe_demo
|
105
|
-
end
|
106
|
-
|
data/lib/tribe/version.rb
CHANGED
data/tribe.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |gem|
|
|
5
5
|
gem.authors = ["Chad Remesch"]
|
6
6
|
gem.email = ["chad@remesch.com"]
|
7
7
|
gem.description = %q{Event driven actors for Ruby}
|
8
|
-
gem.summary = %q{Event driven actors for Ruby
|
8
|
+
gem.summary = %q{Event driven actors for Ruby}
|
9
9
|
gem.homepage = ""
|
10
10
|
|
11
11
|
gem.files = `git ls-files`.split($\)
|
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.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -59,22 +59,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
59
59
|
- - ! '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
|
-
segments:
|
63
|
-
- 0
|
64
|
-
hash: 2679671106278227985
|
65
62
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
63
|
none: false
|
67
64
|
requirements:
|
68
65
|
- - ! '>='
|
69
66
|
- !ruby/object:Gem::Version
|
70
67
|
version: '0'
|
71
|
-
segments:
|
72
|
-
- 0
|
73
|
-
hash: 2679671106278227985
|
74
68
|
requirements: []
|
75
69
|
rubyforge_project:
|
76
70
|
rubygems_version: 1.8.24
|
77
71
|
signing_key:
|
78
72
|
specification_version: 3
|
79
|
-
summary: Event driven actors for Ruby
|
73
|
+
summary: Event driven actors for Ruby
|
80
74
|
test_files: []
|