Add Pool.Stat
This commit is contained in:
@@ -7,10 +7,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
resourceStatusCreating = 0
|
resourceStatusConstructing = 0
|
||||||
resourceStatusIdle = iota
|
resourceStatusIdle = iota
|
||||||
resourceStatusAcquired = iota
|
resourceStatusAcquired = iota
|
||||||
resourceStatusHijacked = iota
|
resourceStatusHijacked = iota
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrClosedPool occurs on an attempt to get a connection from a closed pool.
|
// ErrClosedPool occurs on an attempt to get a connection from a closed pool.
|
||||||
@@ -96,20 +96,59 @@ func (p *Pool) Close() {
|
|||||||
p.destructWG.Wait()
|
p.destructWG.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size returns the current size of the pool.
|
type Stat struct {
|
||||||
func (p *Pool) Size() int {
|
constructing int
|
||||||
p.cond.L.Lock()
|
acquired int
|
||||||
n := len(p.allResources)
|
idle int
|
||||||
p.cond.L.Unlock()
|
maxSize int
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxSize returns the current maximum size of the pool.
|
// Size returns the total number of resources in the pool.
|
||||||
func (p *Pool) MaxSize() int {
|
func (s *Stat) Size() int {
|
||||||
|
return s.constructing + s.acquired + s.idle
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructing returns the number of resources with construction in progress in
|
||||||
|
// the pool.
|
||||||
|
func (s *Stat) Constructing() int {
|
||||||
|
return s.constructing
|
||||||
|
}
|
||||||
|
|
||||||
|
// Acquired returns the number of acquired resources in the pool.
|
||||||
|
func (s *Stat) Acquired() int {
|
||||||
|
return s.acquired
|
||||||
|
}
|
||||||
|
|
||||||
|
// Idle returns the number of idle resources in the pool.
|
||||||
|
func (s *Stat) Idle() int {
|
||||||
|
return s.idle
|
||||||
|
}
|
||||||
|
|
||||||
|
// MaxSize returns the maximum size of the pool
|
||||||
|
func (s *Stat) MaxSize() int {
|
||||||
|
return s.maxSize
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stat returns the current pool statistics.
|
||||||
|
func (p *Pool) Stat() *Stat {
|
||||||
p.cond.L.Lock()
|
p.cond.L.Lock()
|
||||||
n := p.maxSize
|
s := &Stat{
|
||||||
|
maxSize: p.maxSize,
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, res := range p.allResources {
|
||||||
|
switch res.status {
|
||||||
|
case resourceStatusConstructing:
|
||||||
|
s.constructing += 1
|
||||||
|
case resourceStatusIdle:
|
||||||
|
s.idle += 1
|
||||||
|
case resourceStatusAcquired:
|
||||||
|
s.acquired += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
p.cond.L.Unlock()
|
p.cond.L.Unlock()
|
||||||
return n
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Acquire gets a resource from the pool. If no resources are available and the pool
|
// Acquire gets a resource from the pool. If no resources are available and the pool
|
||||||
@@ -142,7 +181,7 @@ func (p *Pool) Acquire(ctx context.Context) (*Resource, error) {
|
|||||||
|
|
||||||
// If there is room to create a resource do so
|
// If there is room to create a resource do so
|
||||||
if len(p.allResources) < p.maxSize {
|
if len(p.allResources) < p.maxSize {
|
||||||
res := &Resource{pool: p, status: resourceStatusCreating}
|
res := &Resource{pool: p, status: resourceStatusConstructing}
|
||||||
p.allResources = append(p.allResources, res)
|
p.allResources = append(p.allResources, res)
|
||||||
p.cond.L.Unlock()
|
p.cond.L.Unlock()
|
||||||
|
|
||||||
|
|||||||
+54
-5
@@ -113,7 +113,7 @@ func TestPoolAcquireDoesNotCreatesResourceWhenItWouldExceedMaxSize(t *testing.T)
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
assert.Equal(t, 1, createCounter.Value())
|
assert.Equal(t, 1, createCounter.Value())
|
||||||
assert.Equal(t, 1, pool.Size())
|
assert.Equal(t, 1, pool.Stat().Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolAcquireWithCancellableContext(t *testing.T) {
|
func TestPoolAcquireWithCancellableContext(t *testing.T) {
|
||||||
@@ -140,7 +140,7 @@ func TestPoolAcquireWithCancellableContext(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
|
|
||||||
assert.Equal(t, 1, createCounter.Value())
|
assert.Equal(t, 1, createCounter.Value())
|
||||||
assert.Equal(t, 1, pool.Size())
|
assert.Equal(t, 1, pool.Stat().Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolAcquireReturnsErrorFromFailedResourceCreate(t *testing.T) {
|
func TestPoolAcquireReturnsErrorFromFailedResourceCreate(t *testing.T) {
|
||||||
@@ -261,6 +261,55 @@ func TestPoolCloseBlocksUntilAllResourcesReleasedAndClosed(t *testing.T) {
|
|||||||
assert.Equal(t, len(resources), closeCalls.Value())
|
assert.Equal(t, len(resources), closeCalls.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPoolStat(t *testing.T) {
|
||||||
|
startWaitChan := make(chan struct{})
|
||||||
|
waitingChan := make(chan struct{})
|
||||||
|
endWaitChan := make(chan struct{})
|
||||||
|
|
||||||
|
var createCalls Counter
|
||||||
|
createFunc := func(ctx context.Context) (interface{}, error) {
|
||||||
|
select {
|
||||||
|
case <-startWaitChan:
|
||||||
|
close(waitingChan)
|
||||||
|
<-endWaitChan
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return createCalls.Next(), nil
|
||||||
|
}
|
||||||
|
pool := puddle.NewPool(createFunc, stubCloseRes, 10)
|
||||||
|
defer pool.Close()
|
||||||
|
|
||||||
|
resAcquired, err := pool.Acquire(context.Background())
|
||||||
|
require.Nil(t, err)
|
||||||
|
|
||||||
|
close(startWaitChan)
|
||||||
|
go func() {
|
||||||
|
res, err := pool.Acquire(context.Background())
|
||||||
|
require.Nil(t, err)
|
||||||
|
res.Release()
|
||||||
|
}()
|
||||||
|
<-waitingChan
|
||||||
|
stat := pool.Stat()
|
||||||
|
|
||||||
|
assert.Equal(t, 2, stat.Size())
|
||||||
|
assert.Equal(t, 1, stat.Constructing())
|
||||||
|
assert.Equal(t, 1, stat.Acquired())
|
||||||
|
assert.Equal(t, 0, stat.Idle())
|
||||||
|
assert.Equal(t, 10, stat.MaxSize())
|
||||||
|
|
||||||
|
resAcquired.Release()
|
||||||
|
|
||||||
|
stat = pool.Stat()
|
||||||
|
assert.Equal(t, 2, stat.Size())
|
||||||
|
assert.Equal(t, 1, stat.Constructing())
|
||||||
|
assert.Equal(t, 0, stat.Acquired())
|
||||||
|
assert.Equal(t, 1, stat.Idle())
|
||||||
|
assert.Equal(t, 10, stat.MaxSize())
|
||||||
|
|
||||||
|
close(endWaitChan)
|
||||||
|
}
|
||||||
|
|
||||||
func TestResourceDestroyRemovesResourceFromPool(t *testing.T) {
|
func TestResourceDestroyRemovesResourceFromPool(t *testing.T) {
|
||||||
createFunc, _ := createCreateResourceFunc()
|
createFunc, _ := createCreateResourceFunc()
|
||||||
var closeCalls Counter
|
var closeCalls Counter
|
||||||
@@ -276,7 +325,7 @@ func TestResourceDestroyRemovesResourceFromPool(t *testing.T) {
|
|||||||
|
|
||||||
res.Hijack()
|
res.Hijack()
|
||||||
|
|
||||||
assert.Equal(t, 0, pool.Size())
|
assert.Equal(t, 0, pool.Stat().Size())
|
||||||
assert.Equal(t, 0, closeCalls.Value())
|
assert.Equal(t, 0, closeCalls.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,9 +337,9 @@ func TestResourceHijackRemovesResourceFromPoolButDoesNotDestroy(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 1, res.Value())
|
assert.Equal(t, 1, res.Value())
|
||||||
|
|
||||||
assert.Equal(t, 1, pool.Size())
|
assert.Equal(t, 1, pool.Stat().Size())
|
||||||
res.Destroy()
|
res.Destroy()
|
||||||
assert.Equal(t, 0, pool.Size())
|
assert.Equal(t, 0, pool.Stat().Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolAcquireReturnsErrorWhenPoolIsClosed(t *testing.T) {
|
func TestPoolAcquireReturnsErrorWhenPoolIsClosed(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user