84 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			1.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package grpc
 | 
						|
 | 
						|
import (
 | 
						|
	"sync"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"google.golang.org/grpc"
 | 
						|
)
 | 
						|
 | 
						|
type pool struct {
 | 
						|
	size int
 | 
						|
	ttl  int64
 | 
						|
 | 
						|
	sync.Mutex
 | 
						|
	conns map[string][]*poolConn
 | 
						|
}
 | 
						|
 | 
						|
type poolConn struct {
 | 
						|
	*grpc.ClientConn
 | 
						|
	created int64
 | 
						|
}
 | 
						|
 | 
						|
func newPool(size int, ttl time.Duration) *pool {
 | 
						|
	return &pool{
 | 
						|
		size:  size,
 | 
						|
		ttl:   int64(ttl.Seconds()),
 | 
						|
		conns: make(map[string][]*poolConn),
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (p *pool) getConn(addr string, opts ...grpc.DialOption) (*poolConn, error) {
 | 
						|
	p.Lock()
 | 
						|
	conns := p.conns[addr]
 | 
						|
	now := time.Now().Unix()
 | 
						|
 | 
						|
	// while we have conns check age and then return one
 | 
						|
	// otherwise we'll create a new conn
 | 
						|
	for len(conns) > 0 {
 | 
						|
		conn := conns[len(conns)-1]
 | 
						|
		conns = conns[:len(conns)-1]
 | 
						|
		p.conns[addr] = conns
 | 
						|
 | 
						|
		// if conn is old kill it and move on
 | 
						|
		if d := now - conn.created; d > p.ttl {
 | 
						|
			conn.ClientConn.Close()
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		// we got a good conn, lets unlock and return it
 | 
						|
		p.Unlock()
 | 
						|
 | 
						|
		return conn, nil
 | 
						|
	}
 | 
						|
 | 
						|
	p.Unlock()
 | 
						|
 | 
						|
	// create new conn
 | 
						|
	cc, err := grpc.Dial(addr, opts...)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	return &poolConn{cc, time.Now().Unix()}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (p *pool) release(addr string, conn *poolConn, err error) {
 | 
						|
	// don't store the conn if it has errored
 | 
						|
	if err != nil {
 | 
						|
		conn.ClientConn.Close()
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// otherwise put it back for reuse
 | 
						|
	p.Lock()
 | 
						|
	conns := p.conns[addr]
 | 
						|
	if len(conns) >= p.size {
 | 
						|
		p.Unlock()
 | 
						|
		conn.ClientConn.Close()
 | 
						|
		return
 | 
						|
	}
 | 
						|
	p.conns[addr] = append(conns, conn)
 | 
						|
	p.Unlock()
 | 
						|
}
 |