Garage Connection Pool

The package Garage-ConnectionPool implements a connection pool of garage connections. It implements the following basic features:

  • connection recycling
  • purging of idle connections
  • configurable grow size
  • configurable connection validation through a block.

This connection pool returns a GAPooledConnection, polymorphic to a normal garage connection. Upon close, the pooled connection is returned to the pool.

Installation

To load garage's connection pool, you can use it's metacello configuration which is published in Garage's repository. The current stable version is 0.1. You can load it using the following expression:

Gofer it
	smalltalkhubUser: 'DBXTalk' project: 'Garage';
	configurationOf: 'GarageConnectionPool';
	loadVersion: '0.1'.

This configuration depends only on garage's core. It will not load a particular driver. If so is desired, please use the corresponding loading group in garage's configurartion to not bloat this configuration.

Basic Usage

A GAConnectionPool creates and serve connections as they are needed. We create and initialize a connection pool by using the forConnectionString: message with a connection string as argument.

pool := GAConnectionPool forConnectionString: 'postgresV2://localhost:5432/postgres?user=postgres&password=postgres'.

Once we have a connection pool, we can ask it for a connection using the getConnection message.

pool := GAConnectionPool forConnectionString: 'postgresV2://localhost:5432/postgres?user=postgres&password=postgres'.
connection := pool getConnection.

If no connections are available but it has space to create more connections, it will create a new connection with the given connection string. If it cannot serve a connection, it will throw an exception notifying so.

Controlling the creation of connections

To avoid creating too many database connections, we can control the maximum number of connections that a connection pool creates with the maxConnections: message. By default, the value of maxConnections is 20. This means, the connection pool will not create more than 20 connections. If we are in this limit and a user asks for a connection to the pool, the pool will try to return an already existing connection that is unused. If no available connections, it will throw an exception notifying so.

pool := GAConnectionPool forConnectionString: 'postgresV2://localhost:5432/postgres?user=postgres&password=postgres'.

pool maxConnections: 2.

connection := pool getConnection.
	" => a connection"
anotherConnection := pool getConnection.
	" => a different connection"

pool getConnection.
	" => An exception!"

The garage connection pool also allows to control the rate in which connections are created. That is, connections are create in batches. By default these batches are of 1 connection. We can specify this rate using the growSize: message. Note that the grow rate will never make the pool grow over its configured maximum number of connections.

Controlling idle connections

To avoid having big numbers of unused or idle connections, we can configure the maximum amount of idle connections accepted by a connection pool using the maxIdleConnections: message. By default the garage connection pool allows 20 idle connections. Idle connections above this number will be closed automatically during the pool's purge phase. The pool's purge phase is executed when the number of returned connections since the last purge is the 75% of the maximum configured number of idle connections.

pool := GAConnectionPool forConnectionString: 'postgresV2://localhost:5432/postgres?user=postgres&password=postgres'.
pool maxIdleConnections: 0.
connection := pool getConnection.
	" => a new connection"

"We return the connection to the pool"
connection close.

"We ask for a connection"
anotherConnection := pool getConnection.
	" => a different connection.
	The old got closed because it was unused"

pool getConnection.
	" => An exception!"

To decide if a connection is still valid or not during the purge phase, garage's connection pool asks by default to the connection if it is connected, using the isConnected message. We can customize this behavior by specifying a validation block with the validationBlock: message. The validation block can contain any arbitrary expression checking if the connection is valid or not. The connection pool will interpret the validation block as follows: -A connection is considered alive if the validation block does not fail. -On the contrary, it will be considered invalid if the validation block throws an exception.

For example, we can customize the validation block as follows:

pool := GAConnectionPool forConnectionString: 'postgresV2://localhost:5432/postgres?user=postgres&password=postgres'.
pool validationBlock: [ :connection | connection execute: 'SELECT 1+1;' ].