2
0

Merge branch 'ellulpatrick-feature-create-resource'

This commit is contained in:
Jack Christensen
2020-02-03 08:14:45 -06:00
2 changed files with 63 additions and 0 deletions
+27
View File
@@ -373,6 +373,33 @@ func (p *Pool) AcquireAllIdle() []*Resource {
return resources return resources
} }
// 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 (p *Pool) CreateResource(ctx context.Context) error {
value, err := p.constructResourceValue(ctx)
if err != nil {
return err
}
res := &Resource{
pool: p,
creationTime: time.Now(),
status: resourceStatusIdle,
value: value,
lastUsedNano: nanotime(),
}
p.cond.L.Lock()
p.allResources = append(p.allResources, res)
p.idleResources = append(p.idleResources, res)
p.destructWG.Add(1)
p.cond.L.Unlock()
return nil
}
// releaseAcquiredResource returns res to the the pool. // releaseAcquiredResource returns res to the the pool.
func (p *Pool) releaseAcquiredResource(res *Resource, lastUsedNano int64) { func (p *Pool) releaseAcquiredResource(res *Resource, lastUsedNano int64) {
p.cond.L.Lock() p.cond.L.Lock()
+36
View File
@@ -245,6 +245,41 @@ func TestPoolAcquireAllIdle(t *testing.T) {
resources[3].Release() resources[3].Release()
} }
func TestPoolCreateResource(t *testing.T) {
constructor, counter := createConstructor()
pool := puddle.NewPool(constructor, stubDestructor, 10)
defer pool.Close()
var err error
err = pool.CreateResource(context.Background())
require.NoError(t, err)
stats := pool.Stat()
assert.EqualValues(t, 1, stats.IdleResources())
res, err := pool.Acquire(context.Background())
require.NoError(t, err)
assert.Equal(t, counter.Value(), res.Value())
assert.True(t, res.LastUsedNanotime() > 0, "should set LastUsedNanotime so that idle calculations can still work")
assert.Equal(t, 1, res.Value())
assert.WithinDuration(t, time.Now(), res.CreationTime(), time.Second)
res.Release()
assert.EqualValues(t, 0, pool.Stat().EmptyAcquireCount(), "should have been a warm resource")
}
func TestPoolCreateResourceReturnsErrorFromFailedResourceCreate(t *testing.T) {
errCreateFailed := errors.New("create failed")
constructor := func(ctx context.Context) (interface{}, error) {
return nil, errCreateFailed
}
pool := puddle.NewPool(constructor, stubDestructor, 10)
err := pool.CreateResource(context.Background())
assert.Equal(t, errCreateFailed, err)
}
func TestPoolCloseClosesAllIdleResources(t *testing.T) { func TestPoolCloseClosesAllIdleResources(t *testing.T) {
constructor, _ := createConstructor() constructor, _ := createConstructor()
@@ -535,6 +570,7 @@ func TestResourcePanicsOnUsageWhenNotAcquired(t *testing.T) {
assert.PanicsWithValue(t, "tried to hijack resource that is not acquired", res.Hijack) assert.PanicsWithValue(t, "tried to hijack resource that is not acquired", res.Hijack)
assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.Value() }) assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.Value() })
assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.CreationTime() }) assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.CreationTime() })
assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.LastUsedNanotime() })
assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.IdleDuration() }) assert.PanicsWithValue(t, "tried to access resource that is not acquired or hijacked", func() { res.IdleDuration() })
} }