-
Notifications
You must be signed in to change notification settings - Fork 50
/
pool.go
75 lines (68 loc) · 1.45 KB
/
pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package gofast
import (
"time"
)
// PoolClient wraps a client and alter the Close
// method for pool return / destroy.
type PoolClient struct {
Client
Err error
returnClient chan<- *PoolClient
expires time.Time
}
// Expired check if the client expired
func (pc *PoolClient) Expired() bool {
return time.Now().After(pc.expires)
}
// Close close the inner client only
// if it is expired. Otherwise it will
// return itself to the pool.
func (pc *PoolClient) Close() error {
if pc.Expired() {
return pc.Client.Close()
}
go func() {
// block wait until the client
// is returned.
pc.returnClient <- pc
}()
return nil
}
// NewClientPool creates a *ClientPool
// from the given ClientFactory and pool
// it to scale with expiration.
func NewClientPool(
clientFactory ClientFactory,
scale uint,
expires time.Duration,
) *ClientPool {
pool := make(chan *PoolClient, scale)
go func() {
for {
c, err := clientFactory()
pc := &PoolClient{
Client: c,
Err: err,
returnClient: pool,
expires: time.Now().Add(expires),
}
pool <- pc
}
}()
return &ClientPool{
createClient: pool,
}
}
// ClientPool pools client created from
// a given ClientFactory.
type ClientPool struct {
createClient <-chan *PoolClient
}
// CreateClient implements ClientFactory
func (p *ClientPool) CreateClient() (c Client, err error) {
pc := <-p.createClient
if c, err = pc, pc.Err; err != nil {
return nil, err
}
return
}