2
0

Add documention

This commit is contained in:
Jack Christensen
2018-12-26 17:17:25 -06:00
parent 383709a0b4
commit fefda73679
2 changed files with 32 additions and 21 deletions
+7 -10
View File
@@ -1,14 +1,11 @@
# Puddle # Puddle
Puddle is a generic resource pool library for Go. 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 concerrency 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.
## TODO ## Features
* Max resource lifetime * Acquire cancellation via context standard library
* Max resource idle time * Statistics API for monitoring pool pressure
* Resource keep alive * No dependencies outside of standard library
* Resource health check - keep alive and health check might be same thing * High performance
* Reset pool * 100% test coverage
* Shrink pool
* Stress test
* Stat - supercede Size, include available resources, checked out resources, get count, slow get count, slow get wait time, total create count, total background error count
+25 -11
View File
@@ -14,12 +14,17 @@ const (
resourceStatusHijacked = iota resourceStatusHijacked = iota
) )
// ErrClosedPool occurs on an attempt to get a connection from a closed pool. // ErrClosedPool occurs on an attempt to acquire a connection from a closed pool
var ErrClosedPool = errors.New("cannot get from closed pool") // or a pool that is closed while the acquire is waiting.
var ErrClosedPool = errors.New("closed pool")
// Constructor is a function called by the pool to construct a resource.
type Constructor func(ctx context.Context) (res interface{}, err error) type Constructor func(ctx context.Context) (res interface{}, err error)
// Destructor is a function called by the pool to destroy a resource.
type Destructor func(res interface{}) type Destructor func(res interface{})
// Resource is the resource handle returned by acquiring from the pool.
type Resource struct { type Resource struct {
value interface{} value interface{}
pool *Pool pool *Pool
@@ -27,10 +32,15 @@ type Resource struct {
status byte status byte
} }
// Value returns the resource value.
func (res *Resource) Value() interface{} { func (res *Resource) Value() interface{} {
if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
panic("tried to access resource that is not acquired or hijacked")
}
return res.value return res.value
} }
// Release returns the resource to the pool. res must not be subsequently used.
func (res *Resource) Release() { func (res *Resource) Release() {
if res.status != resourceStatusAcquired { if res.status != resourceStatusAcquired {
panic("tried to release resource that is not acquired") panic("tried to release resource that is not acquired")
@@ -38,6 +48,8 @@ func (res *Resource) Release() {
res.pool.releaseAcquiredResource(res) res.pool.releaseAcquiredResource(res)
} }
// Destroy returns the resource to the pool for destruction. res must not be
// subsequently used.
func (res *Resource) Destroy() { func (res *Resource) Destroy() {
if res.status != resourceStatusAcquired { if res.status != resourceStatusAcquired {
panic("tried to destroy resource that is not acquired") panic("tried to destroy resource that is not acquired")
@@ -45,8 +57,8 @@ func (res *Resource) Destroy() {
res.pool.destroyAcquiredResource(res) res.pool.destroyAcquiredResource(res)
} }
// Hijack removes the resource from the pool without destroying it. Caller is // Hijack assumes ownership of the resource from the pool. Caller is responsible
// responsible for cleanup of resource value. // for cleanup of resource value.
func (res *Resource) Hijack() { func (res *Resource) Hijack() {
if res.status != resourceStatusAcquired { if res.status != resourceStatusAcquired {
panic("tried to hijack resource that is not acquired") panic("tried to hijack resource that is not acquired")
@@ -56,13 +68,13 @@ func (res *Resource) Hijack() {
// CreationTime returns when the resource was created by the pool. // CreationTime returns when the resource was created by the pool.
func (res *Resource) CreationTime() time.Time { func (res *Resource) CreationTime() time.Time {
if res.status != resourceStatusAcquired { if !(res.status == resourceStatusAcquired || res.status == resourceStatusHijacked) {
panic("tried to use resource that is not acquired") panic("tried to access resource that is not acquired or hijacked")
} }
return res.creationTime return res.creationTime
} }
// Pool is a thread-safe resource pool. // Pool is a concurrency-safe resource pool.
type Pool struct { type Pool struct {
cond *sync.Cond cond *sync.Cond
destructWG *sync.WaitGroup destructWG *sync.WaitGroup
@@ -82,6 +94,7 @@ type Pool struct {
closed bool closed bool
} }
// NewPool creates a new pool.
func NewPool(constructor Constructor, destructor Destructor, maxSize int) *Pool { func NewPool(constructor Constructor, destructor Destructor, maxSize int) *Pool {
return &Pool{ return &Pool{
cond: sync.NewCond(new(sync.Mutex)), cond: sync.NewCond(new(sync.Mutex)),
@@ -92,8 +105,8 @@ func NewPool(constructor Constructor, destructor Destructor, maxSize int) *Pool
} }
} }
// Close closes all resources in the pool and rejects future Acquire calls. // Close destroys all resources in the pool and rejects future Acquire calls.
// Blocks until all resources are returned to pool and closed. // Blocks until all resources are returned to pool and destroyed.
func (p *Pool) Close() { func (p *Pool) Close() {
p.cond.L.Lock() p.cond.L.Lock()
p.closed = true p.closed = true
@@ -111,6 +124,7 @@ func (p *Pool) Close() {
p.destructWG.Wait() p.destructWG.Wait()
} }
// Stat is a snapshot of Pool statistics.
type Stat struct { type Stat struct {
constructingResources int constructingResources int
acquiredResources int acquiredResources int
@@ -122,7 +136,7 @@ type Stat struct {
canceledAcquireCount int64 canceledAcquireCount int64
} }
// TotalResource returns the total number of resources in the pool. // TotalResource returns the total number of resources.
func (s *Stat) TotalResources() int { func (s *Stat) TotalResources() int {
return s.constructingResources + s.acquiredResources + s.idleResources return s.constructingResources + s.acquiredResources + s.idleResources
} }
@@ -143,7 +157,7 @@ func (s *Stat) IdleResources() int {
return s.idleResources return s.idleResources
} }
// MaxResources returns the maximum size of the pool // MaxResources returns the maximum size of the pool.
func (s *Stat) MaxResources() int { func (s *Stat) MaxResources() int {
return s.maxResources return s.maxResources
} }