tribe_em 0.0.2 → 0.0.3
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 +36 -1
- data/lib/tribe_em/actor_proxy.rb +54 -0
- data/lib/tribe_em/connection.rb +24 -20
- data/lib/tribe_em/dedicated_connection.rb +13 -0
- data/lib/tribe_em/tcp_server.rb +22 -8
- data/lib/tribe_em/version.rb +1 -1
- data/lib/tribe_em.rb +6 -0
- data/tribe_em.gemspec +6 -6
- metadata +5 -3
data/README.md
CHANGED
@@ -19,7 +19,42 @@ Or install it yourself as:
|
|
19
19
|
|
20
20
|
## Usage
|
21
21
|
|
22
|
-
|
22
|
+
You can test the below code using a utility such as telnet (telnet localhost 9000), entering some text, and then killing telnet.
|
23
|
+
|
24
|
+
# Create a custom connection actor class.
|
25
|
+
class EchoConnection < Tribe::EM::Connection
|
26
|
+
private
|
27
|
+
|
28
|
+
def on_post_init(event)
|
29
|
+
puts "Actor (#{identifier}) connected to client using thread (#{Thread.current.object_id})."
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_receive_data(event)
|
33
|
+
puts "Actor (#{identifier}) received data (#{event.data}) using thread (#{Thread.current.object_id})."
|
34
|
+
write(event.data)
|
35
|
+
enqueue(:shutdown)
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_unbind(event)
|
39
|
+
puts "Actor (#{identifier}) disconnected from client using thread (#{Thread.current.object_id})."
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Create your server actor.
|
45
|
+
server = Tribe::EM::TcpServer.new('localhost', 9000, EchoConnection)
|
46
|
+
|
47
|
+
## Customization
|
48
|
+
|
49
|
+
Tribe EM is designed to be easily customized through inheritence of Tribe::EM::Connection.
|
50
|
+
Communication between EventMachine and the Tribe actor system is provided by Tribe::EM::ActorProxy.
|
51
|
+
|
52
|
+
## TODO - missing features
|
53
|
+
|
54
|
+
- Commonly used server protocols such as HTTP.
|
55
|
+
- Integration with my [AMF Socket] (https://github.com/chadrem/amf_socket_ruby "AMF Socket") gem.
|
56
|
+
- Client side sockets.
|
57
|
+
|
23
58
|
|
24
59
|
## Contributing
|
25
60
|
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# Attempt to provide thread-safe communication between EventMachine and Tribe:
|
2
|
+
# 1. Always use EM.schedule to push work to the reactor thread.
|
3
|
+
# 2. Always use @actor.enqueue to push work to the actor's thread pool.
|
4
|
+
|
5
|
+
module Tribe
|
6
|
+
module EM
|
7
|
+
class ActorProxy < ::EM::Connection
|
8
|
+
private
|
9
|
+
|
10
|
+
def initialize(actor_class, options = {})
|
11
|
+
@actor_class = actor_class || raise('You must provide an actor class.')
|
12
|
+
@logger = Workers::LogProxy.new(options[:logger])
|
13
|
+
|
14
|
+
@actor = @actor_class.new({ :actor_proxy => self, :logger => @logger })
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# EM Callbacks. Don't call these directly.
|
19
|
+
#
|
20
|
+
|
21
|
+
public
|
22
|
+
|
23
|
+
def post_init
|
24
|
+
@actor.enqueue(:post_init, nil)
|
25
|
+
end
|
26
|
+
|
27
|
+
def receive_data(data)
|
28
|
+
@actor.enqueue(:receive_data, data)
|
29
|
+
end
|
30
|
+
|
31
|
+
def unbind
|
32
|
+
@actor.enqueue(:unbind, nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# Public methods. Call these from the associated actor.
|
37
|
+
#
|
38
|
+
|
39
|
+
public
|
40
|
+
|
41
|
+
def close(after_writing = false)
|
42
|
+
::EM.schedule { close_connection(after_writing) }
|
43
|
+
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
def write(data)
|
48
|
+
::EM.schedule { send_data(data) }
|
49
|
+
|
50
|
+
return nil
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/tribe_em/connection.rb
CHANGED
@@ -1,39 +1,43 @@
|
|
1
1
|
module Tribe
|
2
2
|
module EM
|
3
|
-
class Connection < ::
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
def post_init
|
8
|
-
enqueue(:post_init, nil)
|
9
|
-
end
|
10
|
-
|
11
|
-
# EM callback. Don't call directly.
|
12
|
-
def receive_data(data)
|
13
|
-
enqueue(:receive_data, data)
|
14
|
-
end
|
15
|
-
|
16
|
-
# EM callback. Don't call directly.
|
17
|
-
def unbind
|
18
|
-
enqueue(:unbind, nil)
|
3
|
+
class Connection < Tribe::Actor
|
4
|
+
# The Proxy class is what cleanly separates the EM connection and Tribe actor.
|
5
|
+
def self.proxy_class
|
6
|
+
return Tribe::EM::ActorProxy
|
19
7
|
end
|
20
8
|
|
21
9
|
private
|
22
10
|
|
23
11
|
def initialize(options = {})
|
24
|
-
|
12
|
+
@actor_proxy = options[:actor_proxy] || raise('You must provide an actor proxy.')
|
13
|
+
|
14
|
+
super
|
25
15
|
end
|
26
16
|
|
27
17
|
def on_post_init(event)
|
28
|
-
puts "Actor (#{identifier}) connected to client using thread (#{Thread.current.object_id})."
|
29
18
|
end
|
30
19
|
|
31
20
|
def on_receive_data(event)
|
32
|
-
puts "Actor (#{identifier}) received data (#{event.data}) using thread (#{Thread.current.object_id})."
|
33
21
|
end
|
34
22
|
|
35
23
|
def on_unbind(event)
|
36
|
-
|
24
|
+
enqueue(:shutdown)
|
25
|
+
end
|
26
|
+
|
27
|
+
def exception_handler(e)
|
28
|
+
close
|
29
|
+
end
|
30
|
+
|
31
|
+
def shutdown_handler(event)
|
32
|
+
close(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
def write(data)
|
36
|
+
@actor_proxy.write(data)
|
37
|
+
end
|
38
|
+
|
39
|
+
def close(after_writing = false)
|
40
|
+
@actor_proxy.close(after_writing)
|
37
41
|
end
|
38
42
|
end
|
39
43
|
end
|
data/lib/tribe_em/tcp_server.rb
CHANGED
@@ -3,12 +3,12 @@ module Tribe
|
|
3
3
|
class TcpServer < Tribe::Actor
|
4
4
|
private
|
5
5
|
|
6
|
-
def initialize(ip, port,
|
6
|
+
def initialize(ip, port, actor_class, options = {})
|
7
7
|
super(options)
|
8
8
|
|
9
|
-
@ip = ip
|
10
|
-
@port = port
|
11
|
-
@
|
9
|
+
@ip = ip || raise('IP is required.')
|
10
|
+
@port = port || raise('Port is required.')
|
11
|
+
@actor_class = actor_class || raise('Actor class is required.')
|
12
12
|
|
13
13
|
start_listener
|
14
14
|
end
|
@@ -21,21 +21,35 @@ module Tribe
|
|
21
21
|
stop_listener
|
22
22
|
end
|
23
23
|
|
24
|
+
def on_listener_started(event)
|
25
|
+
@server_sig = event.data
|
26
|
+
end
|
27
|
+
|
28
|
+
def on_listener_stopped(event)
|
29
|
+
@server_sig = nil
|
30
|
+
end
|
31
|
+
|
24
32
|
def shutdown_handler(event)
|
25
|
-
|
33
|
+
stop_listener if @server_sig
|
26
34
|
end
|
27
35
|
|
28
36
|
def start_listener
|
29
37
|
return if @server_sig
|
30
38
|
|
31
|
-
|
39
|
+
::EM.schedule do
|
40
|
+
sig = ::EM.start_server(@ip, @port, @actor_class.proxy_class, @actor_class, { :logger => @logger })
|
41
|
+
enqueue(:listener_started, sig)
|
42
|
+
end
|
32
43
|
end
|
33
44
|
|
34
45
|
def stop_listener
|
35
46
|
return unless @server_sig
|
36
47
|
|
37
|
-
|
38
|
-
|
48
|
+
sig = @server_sig
|
49
|
+
::EM.schedule do
|
50
|
+
::EM.stop_server(sig)
|
51
|
+
enqueue(:listener_stopped)
|
52
|
+
end
|
39
53
|
end
|
40
54
|
end
|
41
55
|
end
|
data/lib/tribe_em/version.rb
CHANGED
data/lib/tribe_em.rb
CHANGED
@@ -2,7 +2,9 @@ require 'tribe'
|
|
2
2
|
require 'eventmachine'
|
3
3
|
|
4
4
|
require 'tribe_em/version'
|
5
|
+
require 'tribe_em/actor_proxy'
|
5
6
|
require 'tribe_em/connection'
|
7
|
+
require 'tribe_em/dedicated_connection'
|
6
8
|
require 'tribe_em/tcp_server'
|
7
9
|
|
8
10
|
module Tribe
|
@@ -12,6 +14,10 @@ module Tribe
|
|
12
14
|
::EM.run do
|
13
15
|
::EM.kqueue = true if ::EM.kqueue?
|
14
16
|
::EM.epoll = true if ::EM.epoll?
|
17
|
+
|
18
|
+
::EM.error_handler do |e|
|
19
|
+
puts "EXCEPTION: #{e.message}\n#{e.backtrace.join("\n")}--"
|
20
|
+
end
|
15
21
|
end
|
16
22
|
end
|
17
23
|
|
data/tribe_em.gemspec
CHANGED
@@ -4,19 +4,19 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'tribe_em/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |gem|
|
7
|
-
gem.name =
|
7
|
+
gem.name = 'tribe_em'
|
8
8
|
gem.version = Tribe::EM::VERSION
|
9
|
-
gem.authors = [
|
10
|
-
gem.email = [
|
9
|
+
gem.authors = ['Chad Remesch']
|
10
|
+
gem.email = ['chad@remesch.com']
|
11
11
|
gem.description = %q{Event driven network IO for the Tribe gem.}
|
12
12
|
gem.summary = %q{Quickly create network servers using EventMachine and Tribe.}
|
13
|
-
gem.homepage =
|
13
|
+
gem.homepage = 'https://github.com/chadrem/tribe_em'
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
16
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = [
|
18
|
+
gem.require_paths = ['lib']
|
19
19
|
|
20
|
-
gem.add_dependency('tribe',
|
20
|
+
gem.add_dependency('tribe', '0.0.8')
|
21
21
|
gem.add_dependency('eventmachine', '>= 1.0.0')
|
22
22
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tribe_em
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
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-
|
12
|
+
date: 2013-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: tribe
|
@@ -56,7 +56,9 @@ files:
|
|
56
56
|
- README.md
|
57
57
|
- Rakefile
|
58
58
|
- lib/tribe_em.rb
|
59
|
+
- lib/tribe_em/actor_proxy.rb
|
59
60
|
- lib/tribe_em/connection.rb
|
61
|
+
- lib/tribe_em/dedicated_connection.rb
|
60
62
|
- lib/tribe_em/tcp_server.rb
|
61
63
|
- lib/tribe_em/version.rb
|
62
64
|
- tribe_em.gemspec
|
@@ -80,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
82
|
version: '0'
|
81
83
|
requirements: []
|
82
84
|
rubyforge_project:
|
83
|
-
rubygems_version: 1.8.
|
85
|
+
rubygems_version: 1.8.25
|
84
86
|
signing_key:
|
85
87
|
specification_version: 3
|
86
88
|
summary: Quickly create network servers using EventMachine and Tribe.
|