Ensure that conditional variable is signaled if resource failed to create
This commit is contained in:
@@ -316,6 +316,7 @@ func (p *Pool) Acquire(ctx context.Context) (*Resource, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p.cond.L.Unlock()
|
p.cond.L.Unlock()
|
||||||
|
p.cond.Signal()
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -634,6 +635,36 @@ func TestPoolAcquireReturnsErrorWhenPoolIsClosed(t *testing.T) {
|
|||||||
assert.Nil(t, res)
|
assert.Nil(t, res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSignalIsSentWhenResourceFailedToCreate(t *testing.T) {
|
||||||
|
var c Counter
|
||||||
|
constructor := func(context.Context) (a interface{}, err error) {
|
||||||
|
if c.Next() == 2 {
|
||||||
|
return nil, errors.New("outage")
|
||||||
|
}
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
destructor := func(value interface{}) {}
|
||||||
|
|
||||||
|
pool := puddle.NewPool(constructor, destructor, 1)
|
||||||
|
|
||||||
|
res1, err := pool.Acquire(context.Background())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(name string) {
|
||||||
|
defer wg.Done()
|
||||||
|
_, _ = pool.Acquire(context.Background())
|
||||||
|
}(strconv.Itoa(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that both goroutines above are waiting for condition variable signal
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
res1.Destroy()
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
func TestStress(t *testing.T) {
|
func TestStress(t *testing.T) {
|
||||||
constructor, _ := createConstructor()
|
constructor, _ := createConstructor()
|
||||||
var destructorCalls Counter
|
var destructorCalls Counter
|
||||||
|
|||||||
Reference in New Issue
Block a user