2
0

Add more docs and example

This commit is contained in:
Jack Christensen
2018-12-26 18:36:59 -06:00
parent 893989abad
commit 5cb5ce10c3
3 changed files with 121 additions and 0 deletions
+30
View File
@@ -13,6 +13,36 @@ Puddle is a tiny generic resource pool library for Go that uses the standard con
* High performance * High performance
* 100% test coverage * 100% test coverage
## Example Usage
```go
constructor := func(context.Context) (interface{}, error) {
return net.Dial("tcp", "127.0.0.1:8080")
}
destructor := func(value interface{}) {
value.(net.Conn).Close()
}
maxPoolSize := 10
pool := puddle.NewPool(constructor, destructor, maxPoolSize)
// Acquire resource from the pool.
res, err := pool.Acquire(context.Background())
if err != nil {
// ...
}
// Use resource.
_, err = res.Value().(net.Conn).Write([]byte{1})
if err != nil {
// ...
}
// Release when done.
res.Release()
```
## License ## License
MIT MIT
+11
View File
@@ -0,0 +1,11 @@
// Package puddle is a generic resource pool.
/*
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.
*/
package puddle
+80
View File
@@ -4,7 +4,9 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"log"
"math/rand" "math/rand"
"net"
"os" "os"
"sync" "sync"
"testing" "testing"
@@ -589,6 +591,84 @@ func TestStress(t *testing.T) {
pool.Close() pool.Close()
} }
func exampleDummyServer(laddr string, acceptCount int, recvCountChan chan int) {
ln, err := net.Listen("tcp", laddr)
if err != nil {
log.Fatalln("Listen:", err)
}
for i := 0; i < acceptCount; i++ {
conn, err := ln.Accept()
if err != nil {
log.Fatalln("Accept:", err)
}
go func() {
recvCount := 0
for {
buf := make([]byte, 1)
_, err := conn.Read(buf)
if err != nil {
recvCountChan <- recvCount
return
}
recvCount += 1
}
}()
}
}
func Example_Pool() {
// Dummy server
maxPoolSize := 4
serverRecvCountChan := make(chan int)
laddr := "127.0.0.1:8080"
// exampleDummyServer only listens maxPoolSize times so if the pool tried to
// connect more than that the pool would receive an error.
go exampleDummyServer(laddr, maxPoolSize, serverRecvCountChan)
// Pool usage
pool := puddle.NewPool(
func(context.Context) (interface{}, error) { return net.Dial("tcp", laddr) },
func(value interface{}) { value.(net.Conn).Close() },
maxPoolSize,
)
clientCount := 32
opPerClientCount := 100
wg := &sync.WaitGroup{}
for i := 0; i < clientCount; i++ {
wg.Add(1)
go func() {
for i := 0; i < opPerClientCount; i++ {
res, err := pool.Acquire(context.Background())
if err != nil {
log.Fatalln("Acquire", err)
}
_, err = res.Value().(net.Conn).Write([]byte{1})
if err != nil {
log.Fatalln("Write", err)
}
res.Release()
}
wg.Done()
}()
}
wg.Wait()
pool.Close()
totalRecv := <-serverRecvCountChan
totalRecv += <-serverRecvCountChan
totalRecv += <-serverRecvCountChan
totalRecv += <-serverRecvCountChan
fmt.Println("Ops:", totalRecv)
// Output:
// Ops: 3200
}
func BenchmarkPoolAcquireAndRelease(b *testing.B) { func BenchmarkPoolAcquireAndRelease(b *testing.B) {
benchmarks := []struct { benchmarks := []struct {
poolSize int poolSize int