puddle

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2022 License: MIT Imports: 5 Imported by: 20

README

Build Status

Puddle

Puddle is a tiny generic resource pool library for Go that uses the standard context library to signal cancellation of acquires. It is designed to contain the minimum functionality required for a resource pool. It can be used directly or it can be used as the base for a domain specific resource pool. For example, a database connection pool may use puddle internally and implement health checks and keep-alive behavior without needing to implement any concurrent code of its own.

Features

  • Acquire cancellation via context standard library
  • Statistics API for monitoring pool pressure
  • No dependencies outside of standard library
  • High performance
  • 100% test coverage

Example Usage

constructor := func(context.Context) (interface{}, error) {
  return net.Dial("tcp", "127.0.0.1:8080")
}
destructor := func(value interface{}) {
  value.(net.Conn).Close()
}
maxPoolSize := 10

pool := puddle.NewPool(constructor, destructor, maxPoolSize)

// Acquire resource from the pool.
res, err := pool.Acquire(context.Background())
if err != nil {
  // ...
}

// Use resource.
_, err = res.Value().(net.Conn).Write([]byte{1})
if err != nil {
  // ...
}

// Release when done.
res.Release()

Status

Puddle v1 is complete. No changes are planned.

  • Bug reports and fixes are welcome.
  • New features will not be accepted if they can be feasibly implemented in a wrapper.
  • Performance optimizations will not be accepted unless the performance issue rises to the level of a bug.

License

MIT

Documentation

Overview

Package puddle is a generic resource pool.

Puddle is a tiny generic resource pool library for Go that uses the standard context library to signal cancellation of acquires. It is designed to contain the minimum functionality a resource pool needs that cannot be implemented without concurrency concerns. For example, a database connection pool may use puddle internally and implement health checks and keep-alive behavior without needing to implement any concurrent code of its own.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrClosedPool = errors.New("closed pool")

ErrClosedPool occurs on an attempt to acquire a connection from a closed pool or a pool that is closed while the acquire is waiting.

View Source
var ErrNotAvailable = errors.New("resource not available")

ErrNotAvailable occurs on an attempt to acquire a resource from a pool that is at maximum capacity and has no available resources.

Functions

This section is empty.

Types

type Constructor

type Constructor func(ctx context.Context) (res interface{}, err error)

Constructor is a function called by the pool to construct a resource.

type Destructor

type Destructor func(res interface{})

Destructor is a function called by the pool to destroy a resource.

type Pool

type Pool struct {
	// contains filtered or unexported fields
}

Pool is a concurrency-safe resource pool.

Example
package main

import (
	"context"
	"fmt"
	"log"
	"net"

	"github.com/jackc/puddle"
)

func startAcceptOnceDummyServer(laddr string) {
	ln, err := net.Listen("tcp", laddr)
	if err != nil {
		log.Fatalln("Listen:", err)
	}

	go func() {
		conn, err := ln.Accept()
		if err != nil {
			log.Fatalln("Accept:", err)
		}

		for {
			buf := make([]byte, 1)
			_, err := conn.Read(buf)
			if err != nil {
				return
			}
		}
	}()

}

func main() {
	// Dummy server
	laddr := "127.0.0.1:8080"
	startAcceptOnceDummyServer(laddr)

	// Pool creation
	constructor := func(context.Context) (interface{}, error) {
		return net.Dial("tcp", laddr)
	}
	destructor := func(value interface{}) {
		value.(net.Conn).Close()
	}
	maxPoolSize := int32(10)

	pool := puddle.NewPool(constructor, destructor, maxPoolSize)

	// Use pool multiple times
	for i := 0; i < 10; i++ {
		// Acquire resource
		res, err := pool.Acquire(context.Background())
		if err != nil {
			log.Fatalln("Acquire", err)
		}

		// Type-assert value and use
		_, err = res.Value().(net.Conn).Write([]byte{1})
		if err != nil {
			log.Fatalln("Write", err)
		}

		// Release when done.
		res.Release()
	}

	stats := pool.Stat()
	pool.Close()

	fmt.Println("Connections:", stats.TotalResources())
	fmt.Println("Acquires:", stats.AcquireCount())
}
Output:

Connections: 1
Acquires: 10

func NewPool

func NewPool(constructor Constructor, destructor Destructor, maxSize int32) *Pool

NewPool creates a new pool. Panics if maxSize is less than 1.

func (*Pool) Acquire

func (p *Pool) Acquire(ctx context.Context) (*Resource, error)

Acquire gets a resource from the pool. If no resources are available and the pool is not at maximum capacity it will create a new resource. If the pool is at maximum capacity it will block until a resource is available. ctx can be used to cancel the Acquire.

func (*Pool) AcquireAllIdle

func (p *Pool) AcquireAllIdle() []*Resource

AcquireAllIdle atomically acquires all currently idle resources. Its intended use is for health check and keep-alive functionality. It does not update pool statistics.

func (*Pool) Close

func (p *Pool) Close()

Close destroys all resources in the pool and rejects future Acquire calls. Blocks until all resources are returned to pool and destroyed.

func (*Pool) CreateResource added in v1.1.0

func (p *Pool) CreateResource(ctx context.Context) error

CreateResource constructs a new resource without acquiring it. It goes straight in the IdlePool. It does not check against maxSize. It can be useful to maintain warm resources under little load.

func (*Pool) Stat

func (p *Pool) Stat() *Stat

Stat returns the current pool statistics.

func (*Pool) TryAcquire added in v1.2.0

func (p *Pool) TryAcquire(ctx context.Context) (*Resource, error)

TryAcquire gets a resource from the pool if one is immediately available. If not, it returns ErrNotAvailable. If no resources are available but the pool has room to grow, a resource will be created in the background. ctx is only used to cancel the background creation.

type Resource

type Resource struct {
	// contains filtered or unexported fields
}

Resource is the resource handle returned by acquiring from the pool.

func (*Resource) CreationTime

func (res *Resource) CreationTime() time.Time

CreationTime returns when the resource was created by the pool.

func (*Resource) Destroy

func (res *Resource) Destroy()

Destroy returns the resource to the pool for destruction. res must not be subsequently used.

func (*Resource) Hijack

func (res *Resource) Hijack()

Hijack assumes ownership of the resource from the pool. Caller is responsible for cleanup of resource value.

func (*Resource) IdleDuration added in v1.1.0

func (res *Resource) IdleDuration() time.Duration

IdleDuration returns the duration since Release was last called on the resource. This is equivalent to subtracting LastUsedNanotime to the current nanotime.

func (*Resource) LastUsedNanotime added in v1.1.0

func (res *Resource) LastUsedNanotime() int64

LastUsedNanotime returns when Release was last called on the resource measured in nanoseconds from an arbitrary time (a monotonic time). Returns creation time if Release has never been called. This is only useful to compare with other calls to LastUsedNanotime. In almost all cases, IdleDuration should be used instead.

func (*Resource) Release

func (res *Resource) Release()

Release returns the resource to the pool. res must not be subsequently used.

func (*Resource) ReleaseUnused added in v1.1.0

func (res *Resource) ReleaseUnused()

ReleaseUnused returns the resource to the pool without updating when it was last used used. i.e. LastUsedNanotime will not change. res must not be subsequently used.

func (*Resource) Value

func (res *Resource) Value() interface{}

Value returns the resource value.

type Stat

type Stat struct {
	// contains filtered or unexported fields
}

Stat is a snapshot of Pool statistics.

func (*Stat) AcquireCount

func (s *Stat) AcquireCount() int64

AcquireCount returns the cumulative count of successful acquires from the pool.

func (*Stat) AcquireDuration

func (s *Stat) AcquireDuration() time.Duration

AcquireDuration returns the total duration of all successful acquires from the pool.

func (*Stat) AcquiredResources

func (s *Stat) AcquiredResources() int32

AcquiredResources returns the number of currently acquired resources in the pool.

func (*Stat) CanceledAcquireCount

func (s *Stat) CanceledAcquireCount() int64

CanceledAcquireCount returns the cumulative count of acquires from the pool that were canceled by a context.

func (*Stat) ConstructingResources

func (s *Stat) ConstructingResources() int32

ConstructingResources returns the number of resources with construction in progress in the pool.

func (*Stat) EmptyAcquireCount

func (s *Stat) EmptyAcquireCount() int64

EmptyAcquireCount returns the cumulative count of successful acquires from the pool that waited for a resource to be released or constructed because the pool was empty.

func (*Stat) IdleResources

func (s *Stat) IdleResources() int32

IdleResources returns the number of currently idle resources in the pool.

func (*Stat) MaxResources

func (s *Stat) MaxResources() int32

MaxResources returns the maximum size of the pool.

func (*Stat) TotalResources

func (s *Stat) TotalResources() int32

TotalResource returns the total number of resources currently in the pool. The value is the sum of ConstructingResources, AcquiredResources, and IdleResources.

Jump to

Keyboard shortcuts

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