committed by
Jack Christensen
parent
228d0e587b
commit
021a5cc1a6
@@ -265,10 +265,30 @@ func (p *Pool) Acquire(ctx context.Context) (*Resource, error) {
|
|||||||
return p.doAcquire(ctx, true)
|
return p.doAcquire(ctx, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TryAcquire gets a resource from the pool. TryAcquire is the same as Acquire except
|
// TryAcquire gets a resource from the pool if one is immediately available. If not, it returns ErrNotAvailable. If no
|
||||||
// it returns ErrNotAvailable if the pool is at maximum capacity and no resources are available.
|
// 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.
|
||||||
func (p *Pool) TryAcquire(ctx context.Context) (*Resource, error) {
|
func (p *Pool) TryAcquire(ctx context.Context) (*Resource, error) {
|
||||||
return p.doAcquire(ctx, false)
|
p.cond.L.Lock()
|
||||||
|
defer p.cond.L.Unlock()
|
||||||
|
|
||||||
|
if p.closed {
|
||||||
|
return nil, ErrClosedPool
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a resource is available now
|
||||||
|
if len(p.idleResources) > 0 {
|
||||||
|
res := p.idleResources[len(p.idleResources)-1]
|
||||||
|
p.idleResources[len(p.idleResources)-1] = nil // Avoid memory leak
|
||||||
|
p.idleResources = p.idleResources[:len(p.idleResources)-1]
|
||||||
|
p.acquireCount += 1
|
||||||
|
res.status = resourceStatusAcquired
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go p.CreateResource(ctx)
|
||||||
|
|
||||||
|
return nil, ErrNotAvailable
|
||||||
}
|
}
|
||||||
|
|
||||||
// doAcquire implements shared logic behind Acquire and TryAcquire. If block is true
|
// doAcquire implements shared logic behind Acquire and TryAcquire. If block is true
|
||||||
|
|||||||
+9
-2
@@ -175,14 +175,21 @@ func TestPoolAcquireReusesResources(t *testing.T) {
|
|||||||
assert.Equal(t, 1, createCounter.Value())
|
assert.Equal(t, 1, createCounter.Value())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPoolTryAcquireDoesNotBlock(t *testing.T) {
|
func TestPoolTryAcquire(t *testing.T) {
|
||||||
constructor, createCounter := createConstructor()
|
constructor, createCounter := createConstructor()
|
||||||
pool := puddle.NewPool(constructor, stubDestructor, 1)
|
pool := puddle.NewPool(constructor, stubDestructor, 1)
|
||||||
|
|
||||||
|
// Pool is initially empty so TryAcquire fails but starts construction of resource in the background.
|
||||||
res, err := pool.TryAcquire(context.Background())
|
res, err := pool.TryAcquire(context.Background())
|
||||||
|
require.EqualError(t, err, puddle.ErrNotAvailable.Error())
|
||||||
|
assert.Nil(t, res)
|
||||||
|
|
||||||
|
// Wait for background creation to complete.
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
res, err = pool.TryAcquire(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 1, res.Value())
|
assert.Equal(t, 1, res.Value())
|
||||||
|
|
||||||
defer res.Release()
|
defer res.Release()
|
||||||
|
|
||||||
res, err = pool.TryAcquire(context.Background())
|
res, err = pool.TryAcquire(context.Background())
|
||||||
|
|||||||
Reference in New Issue
Block a user