tribe_em 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -19,7 +19,42 @@ Or install it yourself as:
19
19
 
20
20
  ## Usage
21
21
 
22
- Coming soon.
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
@@ -1,39 +1,43 @@
1
1
  module Tribe
2
2
  module EM
3
- class Connection < ::EM::Connection
4
- include Tribe::Actable
5
-
6
- # EM callback. Don't call directly.
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
- init_actable(options)
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
- puts "Actor (#{identifier}) disconnected from client using thread (#{Thread.current.object_id})."
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
@@ -0,0 +1,13 @@
1
+ module Tribe
2
+ module EM
3
+ class DedicatedConnection < Tribe::EM::Connection
4
+ private
5
+
6
+ def initialize(options = {})
7
+ options[:dedicated] = true
8
+
9
+ super(options)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,12 +3,12 @@ module Tribe
3
3
  class TcpServer < Tribe::Actor
4
4
  private
5
5
 
6
- def initialize(ip, port, conn_class, options = {})
6
+ def initialize(ip, port, actor_class, options = {})
7
7
  super(options)
8
8
 
9
- @ip = ip
10
- @port = port
11
- @conn_class = conn_class
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
- stop_server
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
- @server_sig = ::EM.start_server(@ip, @port, @conn_class)
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
- ::EM.stop_server(@server_sig)
38
- @server_sig = nil
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
@@ -1,5 +1,5 @@
1
1
  module Tribe
2
2
  module EM
3
- VERSION = '0.0.2'
3
+ VERSION = '0.0.3'
4
4
  end
5
5
  end
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 = "tribe_em"
7
+ gem.name = 'tribe_em'
8
8
  gem.version = Tribe::EM::VERSION
9
- gem.authors = ["Chad Remesch"]
10
- gem.email = ["chad@remesch.com"]
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 = "https://github.com/chadrem/tribe_em"
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 = ["lib"]
18
+ gem.require_paths = ['lib']
19
19
 
20
- gem.add_dependency('tribe', ['0.0.8'])
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.2
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-01-27 00:00:00.000000000 Z
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.24
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.