pool

package
v0.0.0-...-b67df6e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 15, 2018 License: MIT Imports: 3 Imported by: 214

Documentation

Overview

Package pool implements a connection pool for redis connections which is thread-safe.

Basic usage

The basic use-case is to create a pool and then pass that pool amongst multiple go-routines, each of which can use it safely. To retrieve a connection you use Get, and to return the connection to the pool when you're done with it you use Put.

p, err := pool.New("tcp", "localhost:6379", 10)
if err != nil {
	// handle error
}

// In another go-routine

conn, err := p.Get()
if err != nil {
	// handle error
}

if conn.Cmd("SOME", "CMD").Err != nil {
	// handle error
}

p.Put(conn)

Options

Various options can be sent to NewCustom to modify the behavior of the pool. Be default, the pool pings a connection every 10/size seconds, creates an unlimited amount of new connections and does not buffer created connections if the pool is full. Each of these can be modified by sending one or more Opt functions to NewCustom.

Shortcuts

If you're doing multiple operations you may find it useful to defer the Put right after retrieving a connection, so that you don't have to always remember to do so

conn, err := p.Get()
if err != nil {
	// handle error
}
defer p.Put(conn)

if conn.Cmd("SOME", "CMD").Err != nil {
	// handle error
}

if conn.Cmd("SOME", "OTHER", "CMD").Err != nil {
	// handle error
}

Additionally there is the Cmd method on Pool, which handles Get-ing and Put-ing for you in the case of only wanting to execute a single command

r := p.Cmd("SOME", "CMD")
if r.Err != nil {
	// handle error
}

Custom connections

Sometimes it's necessary to run some code on each connection in a pool upon its creation, for example in the case of AUTH. This can be done with NewCustom, like so

df := func(network, addr string) (*redis.Client, error) {
	client, err := redis.Dial(network, addr)
	if err != nil {
		return nil, err
	}
	if err = client.Cmd("AUTH", "SUPERSECRET").Err; err != nil {
		client.Close()
		return nil, err
	}
	return client, nil
}
p, err := pool.NewCustom("tcp", "127.0.0.1:6379", 10, df)

Index

Constants

This section is empty.

Variables

View Source
var (

	// ErrGetTimeout is returned from Get when a GetTimeout was specified and
	// that time was hit.
	ErrGetTimeout = errors.New("get timed out")
)

Functions

This section is empty.

Types

type DialFunc

type DialFunc func(network, addr string) (*redis.Client, error)

DialFunc is a function which can be passed into NewCustom

type Opt

type Opt func(*opts)

Opt is an optional behavior which can be applied to the NewCustom function to effect a Pool's behavior

func CreateLimit

func CreateLimit(headroom int, createInterval time.Duration) Opt

CreateLimit effects the Pool's create behavior when the pool is empty. The effect is to limit any connection creation to at most one every interval after headroom has been exhausted. When a request comes in and the pool is empty, new connections will be created as fast as necessary until the headroom is depleated and then any new requests will be blocked until interval happens.

Typically you'll want some headroom over the pool size to allow a burst of traffic to be satisfied as quickly as possible but then limit creation after that initial headroom.

Setting the interval to 0 disables any creation limits. Setting the headroom to 0 disables any headroom and all creation will be limited by the interval.

func GetTimeout

func GetTimeout(timeout time.Duration) Opt

GetTimeout effects the Pool's behavior when it is empty. The effect is to limit the amount of time Get spends waiting for a new connection before timing out and returning ErrGetTimeout.

The timeout does not include the time it takes to dial the new connection since we have no way of cancelling the dial once it has begun.

The default is 0, which disables the timeout.

func OnFullBuffer

func OnFullBuffer(size int, drainInterval time.Duration) Opt

OnFullBuffer effects the Pool's behavior when it is full. The effect is to cause any connection which is being put back into a full pool to be put instead into an overflow buffer which can hold up to the given number of connections. If the overflow buffer is also full then the connection is closed and discarded.

drainInterval specifies the interval at which a drain event happens. On each drain event a connection is removed from the overflow buffer and put into the pool. If the pool is full the connection is closed and discarded.

When Actions are performed with the Pool the connection used may come from either the main pool or the overflow buffer. Connections do _not_ have to wait to be drained into the main pool before they will be used.

func PingInterval

func PingInterval(d time.Duration) Opt

PingInterval specifies the interval at which a ping event happens. On each ping event the Pool calls the PING redis command over one of it's available connections.

Since connections are used in LIFO order, the ping interval * pool size is the duration of time it takes to ping every connection once when the pool is idle.

A shorter interval means connections are pinged more frequently, but also means more traffic with the server.

An interval of 0 disables pinging and is highly discouraged.

type Pool

type Pool struct {

	// The network/address that the pool is connecting to. These are going to be
	// whatever was passed into the New function. These should not be
	// changed after the pool is initialized
	Network, Addr string
	// contains filtered or unexported fields
}

Pool is a connection pool for redis Clients. It will create a small pool of initial connections, and if more connections are needed they will be created on demand. If a connection is Put back and the pool is full it will be closed. A reserve pool is kept alongside the main pool to prevent connection churn. If the main pool is filled, a connection is put into the reserve pool and they're slowly (over 100 seconds) evicted from the reserve.

func New

func New(network, addr string, size int) (*Pool, error)

New creates a new Pool whose connections are all created using redis.Dial(network, addr). The size indicates the maximum number of idle connections to have waiting to be used at any given moment. If an error is encountered an empty (but still usable) pool is returned alongside that error

func NewCustom

func NewCustom(network, addr string, size int, df DialFunc, os ...Opt) (*Pool, error)

NewCustom is like New except you can specify a DialFunc which will be used when creating new connections for the pool. The common use-case is to do authentication for new connections.

func (*Pool) Avail

func (p *Pool) Avail() int

Avail returns the number of connections currently available to be gotten from the Pool using Get. If the number is zero then subsequent calls to Get will be creating new connections on the fly.

func (*Pool) Cmd

func (p *Pool) Cmd(cmd string, args ...interface{}) *redis.Resp

Cmd automatically gets one client from the pool, executes the given command (returning its result), and puts the client back in the pool

func (*Pool) Empty

func (p *Pool) Empty()

Empty removes and calls Close() on all the connections currently in the pool. Assuming there are no other connections waiting to be Put back this method effectively closes and cleans up the pool. The pool cannot be used after Empty is called.

func (*Pool) Get

func (p *Pool) Get() (*redis.Client, error)

Get retrieves an available redis client. If there are none available it will create a new one on the fly

func (*Pool) Put

func (p *Pool) Put(conn *redis.Client)

Put returns a client back to the pool. If the pools are full the client is closed instead. If the client is already closed (due to connection failure or what-have-you) it will not be put back in the pool

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL