Skip to main content

A resource pool implementation

Project description

https://travis-ci.org/smitchell556/cuttlepool.svg?branch=master

CuttlePool is a general purpose, thread-safe resource pooling implementation for use with long lived resources and/or resources that are expensive to instantiate. It’s key features are:

Pool overflow

Creates additional resources if the pool capacity has been reached and will remove the overflow when demand for resources decreases.

Resource harvesting

Any resources that haven’t been returned to the pool and are no longer referenced by anything outside the pool are returned to the pool. This helps prevent pool depletion when resources aren’t explicitly returned to the pool and the resource wrapper is garbage collected.

Resource queuing

If all else fails and no resource can be immediately found or made, the pool will wait a specified amount of time for a resource to be returned to the pool before raising an exception.

How-to Guide

Using CuttlePool requires subclassing a CuttlePool object with a user defined method normalize_resource() and ping(). The example below uses sqlite3 connections as a resource, but CuttlePool is not limited to connection drivers.

>>> import sqlite3
>>> from cuttlepool import CuttlePool
>>> class SQLitePool(CuttlePool):
...     def normalize_resource(self, resource):
...         resource.row_factory = None
...     def ping(self, resource):
...         try:
...             rv = resource.execute('SELECT 1').fetchall()
...             return (1,) in rv
...         except sqlite3.Error:
...             return False
>>> pool = SQLitePool(factory=sqlite3.connect, database='ricks_lab')

Let’s break this down line by line.

First, the sqlite3 module is imported. sqlite3.connect will be the underlying resource factory.

CuttlePool is imported and subclassed. The normalize_resource() method takes a resource, in this case a sqlite3.Connection instance created by sqlite3.connect, as a parameter and changes it’s properties. This is important because a resource can be modified while it’s outside of the pool and any modifications made during that time will persist; this can have unintended consequences when the resource is later retrieved from the pool.

Next the ping() method is implemented, which also takes a resource, the same as normalize_resource(), as a parameter. ping() ensures the resource is functional; in this case, it checks that the sqlite3.Connection instance is open. If the resource is functional, ping() returns True else it returns False. In the above example, a simple statement is executed and if the expected result is returned, it means the resource is open and True is returned. The implementation of this method is really dependent on the resource created by the pool and may not even be necessary.

Finally an instance of SQLitePool is made. The sqlite3.connect method is passed to the instance along with the database name.

The CuttlePool object and as a result the SQLitePool object accepts any parameters that the underlying resource factory accepts as keyword arguments. There are three other parameters the pool object accepts that are unrelated to the resource factory. capacity sets the max number of resources the pool will hold at any given time. overflow sets the max number of additional resources the pool will create when depleted. All overflow resources will be removed from the pool if the pool is at capacity. timeout sets the amount of time in seconds the pool will wait for a resource to become free if the pool is depleted when a request for a resource is made.

A resource from the pool can be treated the same way as an instance created by the resource factory passed to the pool. In our example a resource can be used just like a sqlite3.Connection instance.

>>> con = pool.get_resource()
>>> cur = con.cursor()
>>> cur.execute(('INSERT INTO garage (invention_name, state) '
...              'VALUES (%s, %s)'), ('Space Cruiser', 'damaged'))
>>> con.commit()
>>> cur.close()
>>> con.close()

Calling close() on the resource returns it to the pool instead of closing it. It is not necessary to call close() though. The pool tracks resources so any unreferenced resources will be collected and returned to the pool. It is still a good idea to call close() though, since explicit is better than implicit.

To automatically “close” resources, get_resource() can be used in a with statement.

>>> with pool.get_resource() as con:
...     cur = con.cursor()
...     cur.execute(('INSERT INTO garage (invention_name, state) '
...                  'VALUES (%s, %s)'), ('Space Cruiser', 'damaged'))
...     con.commit()
...     cur.close()

API

The API can be found at read the docs.

FAQ

How do I install it?

pip install cuttlepool

Contributing

It’s highly recommended to develop in a virtualenv.

Fork the repository.

Clone the repository:

git clone https://github.com/<your_username>/cuttlepool.git

Install the package in editable mode:

cd cuttlepool
pip install -e .[dev]

Now you’re set. See the next section for running tests.

Running the tests

Tests can be run with the command pytest.

Where can I get help?

If you haven’t read the How-to guide above, please do that first. Otherwise, check the issue tracker. Your issue may be addressed there and if it isn’t please file an issue :)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cuttlepool-0.9.1.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

cuttlepool-0.9.1-py3-none-any.whl (8.7 kB view details)

Uploaded Python 3

File details

Details for the file cuttlepool-0.9.1.tar.gz.

File metadata

  • Download URL: cuttlepool-0.9.1.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.40.0 CPython/3.7.3

File hashes

Hashes for cuttlepool-0.9.1.tar.gz
Algorithm Hash digest
SHA256 6676b01e517f9e39c99129e3ee4522aebee6af654968de6e84b950648b3cf26e
MD5 1577d35c00044a343849ccb349bb86fc
BLAKE2b-256 9347014620002fa760bdbc00ca9d42ee7b767bff8d0986ff1b89dfce9f01efc2

See more details on using hashes here.

File details

Details for the file cuttlepool-0.9.1-py3-none-any.whl.

File metadata

  • Download URL: cuttlepool-0.9.1-py3-none-any.whl
  • Upload date:
  • Size: 8.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.40.0 CPython/3.7.3

File hashes

Hashes for cuttlepool-0.9.1-py3-none-any.whl
Algorithm Hash digest
SHA256 b891d5a9a3c58fd28b66f6cd5868abc506b63e41fc5d3a685fb091bb399921fd
MD5 fcbff230c03e9a5189e0060970c2942e
BLAKE2b-256 8572d1b6a6dda86f0c5509d95605f8c4fd19830e436e7a70c4a85591c1d19abd

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page