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 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.