fiber_connection_pool 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ _yardoc
18
18
  doc/
19
19
 
20
20
  Gemfile.lock
21
+ *.orig
data/.travis.yml CHANGED
@@ -3,4 +3,3 @@ script: rake
3
3
  rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
6
- - rbx-19mode
data/README.md CHANGED
@@ -99,6 +99,8 @@ We use it extensively with MySQL connections with Goliath servers by using `Mysq
99
99
  from [em-synchrony](https://github.com/igrigorik/em-synchrony).
100
100
  And for Celluloid by using a patched version of [ruby-mysql](https://github.com/rubencaro/ruby-mysql).
101
101
  By >=0.2 there is no MySQL-specific code, so it can be used with any kind of connection that can be fibered.
102
+ Take a look at the `examples` folder to see it can be used seamlessly with MySQL and MongoDB.
103
+ You could do it the same way with CouchDB, etc. , or anything you would put on a pool inside a fiber reactor.
102
104
 
103
105
  Reacting to connection failure
104
106
  ------------------
@@ -129,7 +131,7 @@ rescue BadQueryMadeMeWorse # rescue and treat only classes on 'treated_exceptio
129
131
  puts "Replacing #{connection.inspect} with a new one!"
130
132
  MyFancyConnection.new
131
133
  end
132
-
134
+
133
135
  rescue Exception => ex # do not treat the rest of exceptions
134
136
 
135
137
  log ex.to_s # -> 'You have a typo on your sql...'
@@ -142,14 +144,14 @@ you execute a block of code over it. It must return a connection instance, and i
142
144
  in place of the failed one. It can be the same instance after being fixed, or maybe a new one.
143
145
  The call to `with_failed_connection` must be made from the very same
144
146
  fiber that raised the exception. The failed connection will be kept out of the pool,
145
- and reserved for treatment, only if the exception is one of the given in `treated_exceptions`.
146
- Otherwise `with_failed_connection` will raise `NoReservedConnection`.
147
+ and reserved for treatment, only if the exception is one of the given in `treated_exceptions`.
148
+ Otherwise `with_failed_connection` will raise `NoReservedConnection`.
147
149
 
148
150
  Also the reference to the failed connection will be lost after any method execution from that
149
- fiber. So you must call `with_failed_connection` before any other method that may acquire a new
151
+ fiber. So you must call `with_failed_connection` before any other method that may acquire a new
150
152
  instance from the pool.
151
153
 
152
- Any reference to a failed connection is released when the fiber is dead, but as you must access
154
+ Any reference to a failed connection is released when the fiber is dead, but as you must access
153
155
  it from the fiber itself, worry should not.
154
156
 
155
157
  Save data
@@ -204,7 +206,8 @@ Supported Platforms
204
206
  -------------------
205
207
 
206
208
  Used in production environments on Ruby 1.9.3 and 2.0.0.
207
- Tested against Ruby 1.9.3, 2.0.0, and rbx-19mode ([See details..](http://travis-ci.org/rubencaro/fiber_connection_pool)).
209
+ Tested against Ruby 1.9.3 and 2.0.0 ([See details..](http://travis-ci.org/rubencaro/fiber_connection_pool)).
210
+ It should work on any platform implementing fibers. There's no further magic involved.
208
211
 
209
212
  More to come !
210
213
  -------------------
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+ gem 'websocket-eventmachine-server'
3
+ gem 'em-synchrony'
4
+ gem 'mongo'
5
+ gem 'fiber_connection_pool'
6
+ gem 'mongo-em-patch', :github => 'rubencaro/mongo-em-patch'
@@ -0,0 +1,37 @@
1
+ require 'websocket-eventmachine-server'
2
+ require 'fiber_connection_pool'
3
+ require 'mongo'
4
+ require 'em-synchrony'
5
+ require 'mongo-em-patch'
6
+ require 'fiber'
7
+
8
+ EM.synchrony do
9
+
10
+ @pool = FiberConnectionPool.new(:size => 5) do
11
+ Mongo::Connection.new.db('bogusdb')
12
+ end
13
+
14
+ WebSocket::EventMachine::Server.start(:host => "0.0.0.0", :port => 3000) do |ws|
15
+
16
+ ws.onopen do
17
+ puts "Client connected"
18
+ end
19
+
20
+ ws.onmessage do |msg, type|
21
+ puts "Received message: #{msg}"
22
+ print '.'
23
+ Fiber.new do
24
+ res = @pool.collection('bogus').find( :$where => "sleep(2000)" ).count
25
+ msg = "Done #{Thread.current.to_s}, #{Fiber.current.to_s} res:#{res.inspect}"
26
+ puts msg
27
+ ws.send msg, :type => type
28
+ end.resume
29
+ end
30
+
31
+ ws.onclose do
32
+ puts "Client disconnected"
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -3,3 +3,4 @@ gem 'goliath'
3
3
  gem 'em-synchrony'
4
4
  gem 'mongo'
5
5
  gem 'fiber_connection_pool'
6
+ gem 'mongo-em-patch', :github => 'rubencaro/mongo-em-patch'
@@ -1,9 +1,7 @@
1
1
  require 'fiber_connection_pool'
2
2
  require 'mongo'
3
3
  require 'em-synchrony'
4
- #require 'em-synchrony/mongo'
5
-
6
- require './mongo-em-patch.rb'
4
+ require 'mongo-em-patch'
7
5
 
8
6
  config['db'] = FiberConnectionPool.new(:size => 5) do
9
7
  Mongo::Connection.new.db('bogusdb')
@@ -5,4 +5,3 @@ gem 'celluloid-io', github: 'celluloid/celluloid-io', branch: 'master'
5
5
  gem 'reel', github: 'celluloid/reel', branch: 'master'
6
6
  gem 'mongo'
7
7
  gem 'fiber_connection_pool'
8
- gem 'em-synchrony'
@@ -4,61 +4,39 @@ require 'fiber'
4
4
  require 'fiber_connection_pool'
5
5
  require 'celluloid/autostart'
6
6
 
7
+ require './mongo-patch.rb'
8
+
7
9
  class Dispatcher
8
10
  include Celluloid::IO
9
11
 
10
12
  def initialize(opts = {})
11
13
  @db_pool_size = opts[:db_pool_size] || 5
12
14
  @pool = FiberConnectionPool.new(:size => @db_pool_size) do
13
- Mongo::MongoClient.new.db('bogusdb')
15
+ Mongo::Connection.new.db('bogusdb')
14
16
  end
15
17
  puts "DB Pool of size #{@db_pool_size} ready..."
16
18
  end
17
19
 
18
20
  def dispatch(request)
19
21
  print '.'
20
- id = @pool.collection("bogus").find({ :$where => 'sleep(2000)' }).count
21
- puts "Done #{Thread.current.to_s}, #{Fiber.current.to_s}"
22
+ res = @pool.collection('bogus').find( :$where => "sleep(2000)" ).count
23
+ puts "Done #{Thread.current.to_s}, #{Fiber.current.to_s} res:#{res.inspect}"
22
24
  request.respond :ok, "hello, world! #{Time.now.strftime('%T')}"
23
25
  end
24
26
  end
25
27
 
26
28
 
27
- class DispatcherPool
28
-
29
- def initialize(opts = {})
30
- @size = opts[:size] || 1
31
- @dispatchers = []
32
- @size.times{ |i| @dispatchers << "dispatcher_#{i}".to_sym }
33
- @dispatchers.each{ |d| Dispatcher.supervise_as d }
34
- @next_dispatcher = 0
35
- puts "Pool of #{@size} dispatchers ready."
36
- end
37
-
38
- def dispatch(request)
39
- d = @next_dispatcher
40
- @next_dispatcher += 1
41
- @next_dispatcher = 0 if @next_dispatcher >= @dispatchers.count
42
- Celluloid::Actor[@dispatchers[d]].dispatch(request)
43
- rescue => ex
44
- puts "Someone died: #{ex}"
45
- request.respond :internal_server_error, "Someone died"
46
- end
47
-
48
- end
49
-
50
-
51
29
  class MyServer < Reel::Server
52
30
 
53
31
  def initialize(host = "127.0.0.1", port = 3000)
54
32
  super(host, port, &method(:on_connection))
55
- @dispatcher = DispatcherPool.new
33
+ Dispatcher.supervise_as :dispatcher
56
34
  puts "Listening on #{host}:#{port}..."
57
35
  end
58
36
 
59
37
  def on_connection(connection)
60
38
  while request = connection.request
61
- @dispatcher.dispatch(request)
39
+ Celluloid::Actor[:dispatcher].dispatch(request)
62
40
  end
63
41
  end
64
42
 
@@ -0,0 +1,63 @@
1
+ require 'fiber'
2
+ require 'celluloid'
3
+
4
+ class MongoTimeoutHandler
5
+ def self.timeout(op_timeout, ex_class, &block)
6
+ f = Fiber.current
7
+ timer = Celluloid::Actor.current.after(op_timeout) { f.resume(nil) }
8
+ res = block.call
9
+ timer.cancel
10
+ res
11
+ end
12
+ end
13
+
14
+ class Mongo::MongoClient
15
+ Timeout = MongoTimeoutHandler
16
+ end
17
+
18
+ class Mongo::Node
19
+ Timeout = MongoTimeoutHandler
20
+ end
21
+
22
+ class Mongo::TCPSocket
23
+ Timeout = MongoTimeoutHandler
24
+ end
25
+
26
+ class Mongo::SSLSocket
27
+ Timeout = MongoTimeoutHandler
28
+ end
29
+
30
+ class Mongo::TCPSocket
31
+
32
+ def initialize(host, port, op_timeout=nil, connect_timeout=nil, opts={})
33
+ @op_timeout = op_timeout || 30
34
+ @connect_timeout = connect_timeout || 30
35
+ @pid = Process.pid
36
+
37
+ # TODO: Prefer ipv6 if server is ipv6 enabled
38
+ @address = Socket.getaddrinfo(host, nil, Socket::AF_INET).first[3]
39
+ @port = port
40
+
41
+ @socket = nil
42
+ connect
43
+ end
44
+
45
+ def connect
46
+ MongoTimeoutHandler.timeout(@connect_timeout, Mongo::ConnectionTimeoutError) do
47
+ @socket = Celluloid::IO::TCPSocket.new(@address, @port)
48
+ end
49
+ end
50
+
51
+ def send(data)
52
+ raise SocketError, 'Not connected yet' if not @socket
53
+ @socket.write(data)
54
+ end
55
+
56
+ def read(maxlen, buffer)
57
+ raise SocketError, 'Not connected yet' if not @socket
58
+ MongoTimeoutHandler.timeout(@op_timeout, Mongo::OperationTimeout) do
59
+ @socket.read(maxlen, buffer)
60
+ end
61
+ end
62
+
63
+ end
data/examples/ws.html ADDED
@@ -0,0 +1,39 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <script>
6
+ var ws;
7
+ function debug(string) {
8
+ var element = document.getElementById("debug");
9
+ var p = document.createElement("p");
10
+ p.appendChild(document.createTextNode(string));
11
+ element.appendChild(p);
12
+ };
13
+ function close_connection(){
14
+ ws.close();
15
+ debug("closed");
16
+ };
17
+ function open_connection(){
18
+ ws = new WebSocket("ws://localhost:3000");
19
+ ws.onmessage = function(evt) { debug("Received: " + evt.data); };
20
+ ws.onclose = function(event) {
21
+ debug("Closed - code: " + event.code + ", reason: " + event.reason + ", wasClean: " + event.wasClean);
22
+ };
23
+ ws.onopen = function() {
24
+ debug("connected...");
25
+ };
26
+ };
27
+ function send_msg(){
28
+ ws.send('hello server');
29
+ debug("message sent...");
30
+ };
31
+ </script>
32
+ </head>
33
+ <body>
34
+ <button onclick="open_connection();">Open</button>
35
+ <button onclick="close_connection();">Close</button>
36
+ <button onclick="send_msg();">Send Msg</button>
37
+ <div id="debug"></div>
38
+ </body>
39
+ </html>
@@ -2,7 +2,7 @@ require 'fiber'
2
2
  require_relative 'fiber_connection_pool/exceptions'
3
3
 
4
4
  class FiberConnectionPool
5
- VERSION = '0.2.3'
5
+ VERSION = '0.2.4'
6
6
 
7
7
  RESERVED_TTL_SECS = 30 # reserved cleanup trigger
8
8
  SAVED_DATA_TTL_SECS = 30 # saved_data cleanup trigger
@@ -99,9 +99,9 @@ class FiberConnectionPool
99
99
 
100
100
  # Avoid method_missing stack for 'query'
101
101
  #
102
- def query(sql)
102
+ def query(sql, *args)
103
103
  execute('query') do |conn|
104
- conn.query sql
104
+ conn.query sql, *args
105
105
  end
106
106
  end
107
107
 
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiber_connection_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Ruben Caro
@@ -9,40 +10,43 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2013-09-14 00:00:00.000000000 Z
13
+ date: 2013-09-23 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: minitest
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
- - - '>='
20
+ - - ! '>='
19
21
  - !ruby/object:Gem::Version
20
22
  version: '0'
21
23
  type: :development
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
- - - '>='
28
+ - - ! '>='
26
29
  - !ruby/object:Gem::Version
27
30
  version: '0'
28
31
  - !ruby/object:Gem::Dependency
29
32
  name: rake
30
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
31
35
  requirements:
32
- - - '>='
36
+ - - ! '>='
33
37
  - !ruby/object:Gem::Version
34
38
  version: '0'
35
39
  type: :development
36
40
  prerelease: false
37
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
38
43
  requirements:
39
- - - '>='
44
+ - - ! '>='
40
45
  - !ruby/object:Gem::Version
41
46
  version: '0'
42
- description: |-
43
- Fiber-based generic connection pool for Ruby, allowing
44
- non-blocking IO behaviour on the same thread
45
- as provided by EventMachine or Celluloid.
47
+ description: ! "Fiber-based generic connection pool for Ruby, allowing\n non-blocking
48
+ IO behaviour on the same thread\n as provided by EventMachine or
49
+ Celluloid."
46
50
  email:
47
51
  - ruben.caro@lanuez.org
48
52
  executables: []
@@ -56,20 +60,23 @@ files:
56
60
  - README.md
57
61
  - Rakefile
58
62
  - examples/.placeholder
59
- - examples/goliath_server/Gemfile
60
- - examples/goliath_server/config/main.rb
61
- - examples/goliath_server/main.rb
63
+ - examples/em_ws_mongo/Gemfile
64
+ - examples/em_ws_mongo/main.rb
62
65
  - examples/goliath_server_em_mongo/Gemfile
63
66
  - examples/goliath_server_em_mongo/config/main.rb
64
67
  - examples/goliath_server_em_mongo/main.rb
65
68
  - examples/goliath_server_mongo/Gemfile
66
69
  - examples/goliath_server_mongo/config/main.rb
67
70
  - examples/goliath_server_mongo/main.rb
68
- - examples/goliath_server_mongo/mongo-em-patch.rb
69
- - examples/reel_server/Gemfile
70
- - examples/reel_server/main.rb
71
+ - examples/goliath_server_mysql/Gemfile
72
+ - examples/goliath_server_mysql/config/main.rb
73
+ - examples/goliath_server_mysql/main.rb
71
74
  - examples/reel_server_mongo/Gemfile
72
75
  - examples/reel_server_mongo/main.rb
76
+ - examples/reel_server_mongo/mongo-patch.rb
77
+ - examples/reel_server_mysql/Gemfile
78
+ - examples/reel_server_mysql/main.rb
79
+ - examples/ws.html
73
80
  - fiber_connection_pool.gemspec
74
81
  - lib/fiber_connection_pool.rb
75
82
  - lib/fiber_connection_pool/exceptions.rb
@@ -78,26 +85,27 @@ files:
78
85
  homepage: https://github.com/rubencaro/fiber_connection_pool
79
86
  licenses:
80
87
  - GPLv3
81
- metadata: {}
82
88
  post_install_message:
83
89
  rdoc_options: []
84
90
  require_paths:
85
91
  - lib
86
92
  required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
87
94
  requirements:
88
- - - '>='
95
+ - - ! '>='
89
96
  - !ruby/object:Gem::Version
90
97
  version: 1.9.2
91
98
  required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
92
100
  requirements:
93
- - - '>='
101
+ - - ! '>='
94
102
  - !ruby/object:Gem::Version
95
103
  version: '0'
96
104
  requirements: []
97
105
  rubyforge_project:
98
- rubygems_version: 2.0.6
106
+ rubygems_version: 1.8.25
99
107
  signing_key:
100
- specification_version: 4
108
+ specification_version: 3
101
109
  summary: Fiber-based generic connection pool for Ruby
102
110
  test_files:
103
111
  - test/fiber_connection_pool_test.rb
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 340c349ed71fd516c16b2ec7ff01b6de4fb65072
4
- data.tar.gz: 31d1a2a20a195afa721c39ee2c8a65171fc0f8a2
5
- SHA512:
6
- metadata.gz: 23daf95d4cb681737c91c94172503be106ea0f518ab26f140025c840367fc92abcc922089a46cc3e5c6844f87458da0a03e4f4dc0835d9defadbf3e987e2a8db
7
- data.tar.gz: 269f02b50cda24eb6a0e23e683ee74060d4c57de74ed1e3827349c01872df0e89e802211c256fb152714e7ccb6a50dbedc67a237c9e154dfb5b6326ec848a0be
@@ -1,85 +0,0 @@
1
- require 'fiber'
2
-
3
- class EventMachine::Synchrony::MongoTimeoutHandler
4
- def self.timeout(op_timeout, ex_class, &block)
5
- f = Fiber.current
6
- timer = EM::Timer.new(op_timeout) { f.resume(nil) }
7
- res = block.call
8
- timer.cancel
9
- res
10
- end
11
- end
12
-
13
- class Mongo::Connection
14
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
15
- end
16
-
17
- class Mongo::MongoClient
18
- ConditionVariable = ::EventMachine::Synchrony::Thread::ConditionVariable
19
- Timeout = ::EventMachine::Synchrony::MongoTimeoutHandler
20
- end
21
-
22
- class Mongo::Pool
23
- ConditionVariable = ::EventMachine::Synchrony::Thread::ConditionVariable
24
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
25
- end
26
-
27
- class Mongo::Node
28
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
29
- Timeout = ::EventMachine::Synchrony::MongoTimeoutHandler
30
- end
31
-
32
- class Mongo::TCPSocket
33
- Timeout = ::EventMachine::Synchrony::MongoTimeoutHandler
34
- end
35
-
36
- class Mongo::SSLSocket
37
- Timeout = ::EventMachine::Synchrony::MongoTimeoutHandler
38
- end
39
-
40
- class Mongo::MongoReplicaSetClient
41
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
42
- end
43
-
44
- class Mongo::MongoShardedClient
45
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
46
- end
47
-
48
- class Mongo::PoolManager
49
- Mutex = ::EventMachine::Synchrony::Thread::Mutex
50
- end
51
-
52
- class Mongo::TCPSocket
53
-
54
- def initialize(host, port, op_timeout=nil, connect_timeout=nil, opts={})
55
- @op_timeout = op_timeout || 30
56
- @connect_timeout = connect_timeout || 30
57
- @pid = Process.pid
58
-
59
- # TODO: Prefer ipv6 if server is ipv6 enabled
60
- @address = Socket.getaddrinfo(host, nil, Socket::AF_INET).first[3]
61
- @port = port
62
-
63
- @socket = nil
64
- connect
65
- end
66
-
67
- def connect
68
- ::EventMachine::Synchrony::MongoTimeoutHandler.timeout(@connect_timeout, Mongo::ConnectionTimeoutError) do
69
- @socket = EM::Synchrony::TCPSocket.new(@address, @port)
70
- end
71
- end
72
-
73
- def send(data)
74
- raise SocketError, 'Not connected yet' if not @socket
75
- @socket.write(data)
76
- end
77
-
78
- def read(maxlen, buffer)
79
- raise SocketError, 'Not connected yet' if not @socket
80
- ::EventMachine::Synchrony::MongoTimeoutHandler.timeout(@op_timeout, Mongo::OperationTimeout) do
81
- @socket.read(maxlen, buffer)
82
- end
83
- end
84
-
85
- end