Class: Authorize::Redis::ConnectionManager
- Inherits:
-
Object
- Object
- Authorize::Redis::ConnectionManager
- Defined in:
- lib/authorize/redis/connection_manager.rb
Overview
This class arbitrates access to a Redis server ensuring that threads don’t concurrently access the same connection yehudakatz.com/2010/08/14/threads-in-ruby-enough-already/ blog.headius.com/2008/08/qa-what-thread-safe-rails-means.html Inspired by the ConnectionPool class in Rails 2.3 Notes on thread-safety: Because instances of this class are expected to be shared across threads, access to all non-local variables and “constants” need to be synchronized. We assume that Hash read/assign operations are thread-safe. We also require that the value returned by #current_connection_id not be shared across threads.
Defined Under Namespace
Classes: ConnectionError
Instance Attribute Summary collapse
-
#pool ⇒ Object
readonly
Returns the value of attribute pool.
Instance Method Summary collapse
-
#acquire_connection ⇒ Object
(also: #connection)
Retrieve the connection associated with the current thread, or checkout one from the pool as required.
-
#expire_stale_connections! ⇒ Object
Expire stale connections.
-
#initialize(specification, options = {}) ⇒ ConnectionManager
constructor
Creates a new ConnectionPool object.
-
#recover_unused_connections ⇒ Object
Identifies connections in the death grip of defunct threads, removes them from the map and checks them back into the pool Because this method operates across connections for multiple threads (not just the current thread), concurrent execution needs to be synchronized to be thread-safe.
-
#release_connection ⇒ Object
Signal that the thread is finished with the current connection.
-
#reset! ⇒ Object
Revert to a freshly initialized state.
-
#with_connection ⇒ Object
Checks out a connection from the pool, yields it to a block and checks it back into the pool when the block finishes.
Constructor Details
#initialize(specification, options = {}) ⇒ ConnectionManager
Creates a new ConnectionPool object. specification
is a ConnectionSpecification object which describes database connection parameters
21 22 23 24 25 26 |
# File 'lib/authorize/redis/connection_manager.rb', line 21 def initialize(specification, = {}) @options = {:size => 5}.merge() @pool = ResourcePool.new(@options[:size], lambda {specification.connect!}) @connection_map = {} # Connections mapped to threads @mutex = Monitor.new end |
Instance Attribute Details
#pool ⇒ Object (readonly)
Returns the value of attribute pool.
17 18 19 |
# File 'lib/authorize/redis/connection_manager.rb', line 17 def pool @pool end |
Instance Method Details
#acquire_connection ⇒ Object Also known as: connection
Retrieve the connection associated with the current thread, or checkout one from the pool as required. #connection can be called any number of times; the connection is held in a hash with a thread-specific key.
30 31 32 |
# File 'lib/authorize/redis/connection_manager.rb', line 30 def acquire_connection @connection_map[current_connection_id] ||= @pool.checkout(10) end |
#expire_stale_connections! ⇒ Object
Expire stale connections
66 67 68 69 70 |
# File 'lib/authorize/redis/connection_manager.rb', line 66 def expire_stale_connections! @pool.expire do |connection, reserved_flag| !connection.client.connected? end end |
#recover_unused_connections ⇒ Object
Identifies connections in the death grip of defunct threads, removes them from the map and checks them back into the pool Because this method operates across connections for multiple threads (not just the current thread), concurrent execution needs to be synchronized to be thread-safe.
54 55 56 57 58 59 60 61 62 63 |
# File 'lib/authorize/redis/connection_manager.rb', line 54 def recover_unused_connections tids = Thread.list.select{|t| t.alive?}.map(&:object_id) @mutex.synchronize do cids = @connection_map.keys (cids - tids).each do |sid| c = @connection_map.delete(sid) @pool.checkin(c) end end end |
#release_connection ⇒ Object
Signal that the thread is finished with the current connection. #release_connection releases the connection-thread association and returns the connection to the pool.
38 39 40 41 |
# File 'lib/authorize/redis/connection_manager.rb', line 38 def release_connection c = @connection_map.delete(current_connection_id) @pool.checkin(c) if c end |
#reset! ⇒ Object
Revert to a freshly initialized state
73 74 75 76 77 78 79 |
# File 'lib/authorize/redis/connection_manager.rb', line 73 def reset! @mutex.synchronize do @pool.clear! @connection_map.clear end self end |
#with_connection ⇒ Object
Checks out a connection from the pool, yields it to a block and checks it back into the pool when the block finishes.
44 45 46 47 48 49 |
# File 'lib/authorize/redis/connection_manager.rb', line 44 def with_connection c = @pool.checkout yield c ensure @pool.checkin(c) end |