fiber_connection_pool 0.2.3 → 0.2.4

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