Class: RDBI::Pool

Inherits:
Object
  • Object
show all
Extended by:
Enumerable
Includes:
Enumerable
Defined in:
lib/rdbi/pool.rb

Overview

RDBI::Pool - Connection Pooling.

Pools are named resources that consist of N concurrent connections which all have the same properties. Many group actions can be performed on them, such as disconnecting the entire lot.

RDBI::Pool itself has a global accessor, by way of RDBI::Pool::[], that can access these pools by name. Alternatively, you may access them through the RDBI.pool interface.

Pools are thread-safe and are capable of being resized without disconnecting the culled database handles.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, connect_args, max = 5) ⇒ Pool

Creates a new pool.

  • name: the name of this pool, which will be used to find it in the global accessor.

  • connect_args: an array of arguments that would be passed to RDBI.connect, including the driver name.

  • max: the maximum number of connections to deal with.

Usage:

Pool.new(:fart, [:SQLite3, :database => “/tmp/foo.db”])



86
87
88
89
90
91
92
93
# File 'lib/rdbi/pool.rb', line 86

def initialize(name, connect_args, max=5)
  @handles      = []
  @connect_args = connect_args
  @max          = max
  @last_index   = 0
  @mutex        = Mutex.new
  self.class[name] = self
end

Instance Attribute Details

#handlesObject (readonly)

a list of the pool handles for this object. Do not manipulate this directly.



68
69
70
# File 'lib/rdbi/pool.rb', line 68

def handles
  @handles
end

#last_indexObject (readonly)

the last index corresponding to the latest allocation request.



70
71
72
# File 'lib/rdbi/pool.rb', line 70

def last_index
  @last_index
end

#maxObject (readonly)

the maximum number of items this pool can hold. should only be altered by resize.



72
73
74
# File 'lib/rdbi/pool.rb', line 72

def max
  @max
end

#mutexObject (readonly)

the Mutex for this pool.



74
75
76
# File 'lib/rdbi/pool.rb', line 74

def mutex
  @mutex
end

Class Method Details

.[](name) ⇒ Object

Retrieves a pool object for the name, or nothing if it does not exist.



43
44
45
46
47
48
# File 'lib/rdbi/pool.rb', line 43

def [](name)
  mutex.synchronize do
    @pools ||= { }
    @pools[name.to_sym]
  end
end

.[]=(name, value) ⇒ Object

Sets the pool for the name. This is not recommended for end-user code.



53
54
55
56
57
58
# File 'lib/rdbi/pool.rb', line 53

def []=(name, value)
  mutex.synchronize do
    @pools ||= { }
    @pools[name.to_sym] = value
  end
end

.eachObject

Iterate each pool and get the name of the pool (as a symbol) and the value as a Pool object.



24
25
26
27
28
# File 'lib/rdbi/pool.rb', line 24

def each
  @pools.each do |key, value|
    yield(key, value)
  end
end

.keysObject

obtain the names of each pool.



31
32
33
# File 'lib/rdbi/pool.rb', line 31

def keys
  @pools.keys
end

.mutexObject



60
61
62
# File 'lib/rdbi/pool.rb', line 60

def mutex
  @mutex
end

.valuesObject

obtain the pool objects of each pool.



36
37
38
# File 'lib/rdbi/pool.rb', line 36

def values
  @pools.values
end

Instance Method Details

#add_connectionObject

Add a connection, connecting automatically with the connect arguments supplied to the constructor.



155
156
157
# File 'lib/rdbi/pool.rb', line 155

def add_connection
  add(RDBI.connect(*@connect_args))
end

#disconnectObject

Disconnect all database handles.



146
147
148
149
150
# File 'lib/rdbi/pool.rb', line 146

def disconnect
  mutex.synchronize do
    @handles.each(&:disconnect)
  end
end

#eachObject

Obtain each database handle in the pool.



96
97
98
# File 'lib/rdbi/pool.rb', line 96

def each
  @handles.each { |dbh| yield dbh }
end

#get_dbhObject

Obtain a database handle from the pool. Ordering is round robin.

A new connection may be created if it fills in the pool where a previously empty object existed. Additionally, if the current database handle is disconnected, it will be reconnected.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/rdbi/pool.rb', line 207

def get_dbh
  mutex.synchronize do
    if @last_index >= @max
      @last_index = 0
    end

    # XXX this is longhand for "make sure it's connected before we hand it
    #     off"
    if @handles[@last_index] and !@handles[@last_index].connected?
      @handles[@last_index].reconnect
    elsif !@handles[@last_index]
      @handles[@last_index] = RDBI.connect(*@connect_args)
    end

    dbh = @handles[@last_index]
    @last_index += 1
    dbh
  end
end

#pingObject

Ping all database connections and average out the amount.

Any disconnected handles will be reconnected before this operation starts.



105
106
107
108
109
110
# File 'lib/rdbi/pool.rb', line 105

def ping
  reconnect_if_disconnected
  mutex.synchronize do 
    @handles.inject(1) { |sum,dbh| sum + (dbh.ping || 1) } / @handles.size
  end
end

#reconnectObject

Unconditionally reconnect all database handles.



128
129
130
131
132
# File 'lib/rdbi/pool.rb', line 128

def reconnect
  mutex.synchronize do 
    @handles.each { |dbh| dbh.reconnect } 
  end
end

#reconnect_if_disconnectedObject

Only reconnect the database handles that have not been already connected.



136
137
138
139
140
141
142
# File 'lib/rdbi/pool.rb', line 136

def reconnect_if_disconnected
  mutex.synchronize do 
    @handles.each do |dbh|
      dbh.reconnect unless dbh.connected?
    end
  end
end

#remove(dbh) ⇒ Object

Remove a specific connection. If this connection does not exist in the pool already, nothing will occur.

This database object is not disconnected – it is your responsibility to do so.



165
166
167
168
169
# File 'lib/rdbi/pool.rb', line 165

def remove(dbh)
  mutex.synchronize do
    @handles.reject! { |x| x.object_id == dbh.object_id }
  end
end

#resize(max = 5) ⇒ Object

Resize the pool. If the new pool size is smaller, connections will be forcibly removed, preferring disconnected handles over connected ones.

No database connections are disconnected.

Returns the handles that were removed, if any.



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/rdbi/pool.rb', line 179

def resize(max=5)
  mutex.synchronize do
    in_pool = @handles.select(&:connected?)

    unless (in_pool.size >= max)
      disconnected = @handles.select { |x| !x.connected? }
      if disconnected.size > 0
        in_pool += disconnected[0..(max - in_pool.size - 1)]
      end
    else
      in_pool = in_pool[0..(max-1)]
    end

    rejected = @handles - in_pool

    @max = max
    @handles = in_pool
    rejected
  end
end

#upObject

Asserts that all the pooled handles are connected. Returns true or false depending on the result of that assertion.



116
117
118
119
120
121
122
123
124
# File 'lib/rdbi/pool.rb', line 116

def up
  alive = false

  mutex.synchronize do
    alive = @handles.select { |x| x.ping.nil? }.empty?
  end

  return alive
end