Class: FiberConnectionPool
- Inherits:
-
Object
- Object
- FiberConnectionPool
- Defined in:
- lib/fiber_connection_pool.rb
Constant Summary collapse
- VERSION =
'0.2.4'- RESERVED_TTL_SECS =
reserved cleanup trigger
30- SAVED_DATA_TTL_SECS =
saved_data cleanup trigger
30
Instance Attribute Summary collapse
-
#saved_data ⇒ Object
Returns the value of attribute saved_data.
-
#treated_exceptions ⇒ Object
Returns the value of attribute treated_exceptions.
Instance Method Summary collapse
-
#clear_save_data_requests ⇒ Object
Clear any save_data requests in the pool.
-
#gathered_data ⇒ Object
Return the gathered data for this fiber.
-
#has_connection?(conn) ⇒ Boolean
True if the given connection is anywhere inside the pool.
-
#initialize(opts) ⇒ FiberConnectionPool
constructor
Initializes the pool with ‘size’ instances running the given block to get each one.
-
#query(sql, *args) ⇒ Object
Avoid method_missing stack for ‘query’.
-
#recreate_connection(new_conn) ⇒ Object
DEPRECATED: use with_failed_connection.
-
#release_data(fiber) ⇒ Object
Delete any saved_data for given fiber.
-
#reserved_cleanup ⇒ Object
Delete any reserved held for dead fibers.
-
#save_data(key, &block) ⇒ Object
Add a save_data request to the pool.
-
#save_data_cleanup ⇒ Object
Delete any saved_data held for dead fibers.
-
#save_data_for_fiber ⇒ Object
DEPRECATED: use save_data.
-
#stop_saving_data_for_fiber ⇒ Object
DEPRECATED: use release_data.
-
#with_failed_connection ⇒ Object
Identify the connection that just failed for current fiber.
Constructor Details
#initialize(opts) ⇒ FiberConnectionPool
Initializes the pool with ‘size’ instances running the given block to get each one. Ex:
pool = FiberConnectionPool.new(:size => 5) { MyConnection.new }
17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/fiber_connection_pool.rb', line 17 def initialize(opts) raise ArgumentError.new('size > 0 is mandatory') if opts[:size].to_i <= 0 @saved_data = {} # placeholder for requested save data @reserved = {} # map of in-progress connections @treated_exceptions = [ PlaceholderException ] # list of Exception classes that need further connection treatment @last_reserved_cleanup = Time.now # reserved cleanup trigger @available = [] # pool of free connections @pending = [] # pending reservations (FIFO) @save_data_requests = {} # blocks to be yielded to save data @last_data_cleanup = Time.now # saved_data cleanup trigger @available = Array.new(opts[:size].to_i) { yield } end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &blk) ⇒ Object (private)
Allow the pool to behave as the underlying connection
Yield the connection within execute method and release once it is complete (assumption: fiber will yield while waiting for IO, allowing the reactor run other fibers)
229 230 231 232 233 |
# File 'lib/fiber_connection_pool.rb', line 229 def method_missing(method, *args, &blk) execute(method) do |conn| conn.send(method, *args, &blk) end end |
Instance Attribute Details
#saved_data ⇒ Object
Returns the value of attribute saved_data.
10 11 12 |
# File 'lib/fiber_connection_pool.rb', line 10 def saved_data @saved_data end |
#treated_exceptions ⇒ Object
Returns the value of attribute treated_exceptions.
10 11 12 |
# File 'lib/fiber_connection_pool.rb', line 10 def treated_exceptions @treated_exceptions end |
Instance Method Details
#clear_save_data_requests ⇒ Object
Clear any save_data requests in the pool. No data will be saved after this, unless new requests are added with #save_data.
81 82 83 |
# File 'lib/fiber_connection_pool.rb', line 81 def clear_save_data_requests @save_data_requests = {} end |
#gathered_data ⇒ Object
Return the gathered data for this fiber
74 75 76 |
# File 'lib/fiber_connection_pool.rb', line 74 def gathered_data @saved_data[Fiber.current] end |
#has_connection?(conn) ⇒ Boolean
True if the given connection is anywhere inside the pool
110 111 112 |
# File 'lib/fiber_connection_pool.rb', line 110 def has_connection?(conn) (@available + @reserved.values).include?(conn) end |
#query(sql, *args) ⇒ Object
Avoid method_missing stack for ‘query’
102 103 104 105 106 |
# File 'lib/fiber_connection_pool.rb', line 102 def query(sql, *args) execute('query') do |conn| conn.query sql, *args end end |
#recreate_connection(new_conn) ⇒ Object
DEPRECATED: use with_failed_connection
115 116 117 |
# File 'lib/fiber_connection_pool.rb', line 115 def recreate_connection(new_conn) with_failed_connection { new_conn } end |
#release_data(fiber) ⇒ Object
Delete any saved_data for given fiber
87 88 89 |
# File 'lib/fiber_connection_pool.rb', line 87 def release_data(fiber) @saved_data.delete(fiber) end |
#reserved_cleanup ⇒ Object
Delete any reserved held for dead fibers
140 141 142 143 144 145 |
# File 'lib/fiber_connection_pool.rb', line 140 def reserved_cleanup @last_reserved_cleanup = Time.now @reserved.dup.each do |k,v| release(k) if not k.alive? end end |
#save_data(key, &block) ⇒ Object
Add a save_data request to the pool. The given block will be executed after each successful call to -any- method on the connection. The connection and the method name are passed to the block.
The returned value will be saved in pool.saved_data[key], and will be kept as long as the fiber stays alive.
Ex:
# (...right after pool's creation...)
pool.save_data(:hey_or_hoo) do |conn, method|
return 'hey' if method == 'query'
'hoo'
end
# (...from a reactor fiber...)
myfiber = Fiber.current
pool.query('select anything from anywhere')
puts pool.saved_data[myfiber][:hey_or_hoo]
=> 'hey'
# (...eventually fiber dies...)
puts pool.saved_data[myfiber].inspect
=> nil
68 69 70 |
# File 'lib/fiber_connection_pool.rb', line 68 def save_data(key, &block) @save_data_requests[key] = block end |
#save_data_cleanup ⇒ Object
Delete any saved_data held for dead fibers
93 94 95 96 97 98 |
# File 'lib/fiber_connection_pool.rb', line 93 def save_data_cleanup @saved_data.dup.each do |k,v| @saved_data.delete(k) if not k.alive? end @last_data_cleanup = Time.now end |
#save_data_for_fiber ⇒ Object
DEPRECATED: use save_data
33 34 35 |
# File 'lib/fiber_connection_pool.rb', line 33 def save_data_for_fiber nil end |
#stop_saving_data_for_fiber ⇒ Object
DEPRECATED: use release_data
38 39 40 |
# File 'lib/fiber_connection_pool.rb', line 38 def stop_saving_data_for_fiber @saved_data.delete Fiber.current end |
#with_failed_connection ⇒ Object
Identify the connection that just failed for current fiber. Pass it to the given block, which must return a valid instance of connection. After that, put the new connection into the pool in failed connection’s place. Raises NoReservedConnection if cannot find the failed connection instance.
124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/fiber_connection_pool.rb', line 124 def with_failed_connection bad_conn = @reserved[Fiber.current] raise NoReservedConnection.new if bad_conn.nil? new_conn = yield bad_conn @available.reject!{ |v| v == bad_conn } @reserved.reject!{ |k,v| v == bad_conn } @available.unshift new_conn # try to cleanup begin bad_conn.close rescue end end |