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.


141
142
143
# File 'lib/rdbi/pool.rb', line 141

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

#disconnectObject

Disconnect all database handles.


132
133
134
135
136
# File 'lib/rdbi/pool.rb', line 132

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.


193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/rdbi/pool.rb', line 193

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.


114
115
116
117
118
# File 'lib/rdbi/pool.rb', line 114

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.


122
123
124
125
126
127
128
# File 'lib/rdbi/pool.rb', line 122

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.


151
152
153
154
155
# File 'lib/rdbi/pool.rb', line 151

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.


165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/rdbi/pool.rb', line 165

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