Returned object not currently part of pool
dreamer-zq opened this issue · comments
Dreamer commented
When I encountered the "Returned object not currently part of pool" error, I always recreated the new connection. Why?
jolestar commented
@zhiqiang-bianjie please show your example code.
Dreamer commented
var (
factory PoolFactory
pool *NodePool
ctx = context.Background()
)
func init() {
peersMap := map[string]EndPoint{}
peersMap[generateId(conf.BlockChainMonitorUrl)] = EndPoint{
Address: conf.BlockChainMonitorUrl,
Available: true,
}
factory = PoolFactory{
peersMap: peersMap,
cron: cron.New(),
}
config := gcp.NewDefaultPoolConfig()
config.MaxTotal = conf.MaxConnectionNum
config.MaxIdle = conf.InitConnectionNum
config.MinIdle = conf.InitConnectionNum
config.TestOnBorrow = true
config.TestOnCreate = true
config.TestWhileIdle = true
logger.Info.Printf("MaxTotal %d ", config.MaxTotal)
logger.Info.Printf("MaxIdle %d ", config.MaxIdle)
logger.Info.Printf("MinIdle %d ", config.MinIdle)
pool = &NodePool{
gcp.NewObjectPool(ctx, &factory, config),
}
//自动搜索可用节点
factory.StartCrawlPeers()
}
type EndPoint struct {
Address string
Available bool
}
type NodePool struct {
*gcp.ObjectPool
}
type PoolFactory struct {
peersMap map[string]EndPoint
cron *cron.Cron
}
func ClosePool() {
logger.Info.Printf("release resource :%s", "nodePool")
pool.Close(ctx)
factory.cron.Stop()
}
func (f *PoolFactory) MakeObject(ctx context.Context) (*gcp.PooledObject, error) {
endpoint := f.GetEndPoint()
logger.Info.Printf("PoolFactory MakeObject peer[%v] \n", endpoint)
return gcp.NewPooledObject(newClient(endpoint.Address)), nil
}
func (f *PoolFactory) DestroyObject(ctx context.Context, object *gcp.PooledObject) error {
logger.Info.Printf("PoolFactory DestroyObject peer[%v] \n",object.Object)
c := object.Object.(*Client)
if c.IsRunning() {
c.Stop()
}
return nil
}
func (f *PoolFactory) ValidateObject(ctx context.Context, object *gcp.PooledObject) bool {
// do validate
logger.Info.Printf("PoolFactory ValidateObject peer[%v] \n",object.Object)
c := object.Object.(*Client)
if c.HeartBeat() != nil {
if endPoint, ok := f.peersMap[c.Id]; ok {
endPoint.Available = false
f.peersMap[c.Id] = endPoint
}
return false
}
return true
}
func (f *PoolFactory) ActivateObject(ctx context.Context, object *gcp.PooledObject) error {
// do activate
//c := object.Object.(*Client)
//err := c.HeartBeat()
//if err != nil {
// if endPoint, ok := f.peersMap[c.Id]; ok {
// logger.Info.Printf("PoolFactory ActivateObject peer[%s] is unavailable \n", endPoint.Address)
// endPoint.Available = false
// f.peersMap[c.Id] = endPoint
// }
//}
logger.Info.Printf("PoolFactory ActivateObject peer[%v] \n",object.Object)
return nil
}
func (f *PoolFactory) PassivateObject(ctx context.Context, object *gcp.PooledObject) error {
// do passivate
//c := object.Object.(*Client)
//err := c.HeartBeat()
//if err != nil {
// if endPoint, ok := f.peersMap[c.Id]; ok {
// logger.Info.Printf("PoolFactory peer[%s] is unavailable \n", endPoint.Address)
// endPoint.Available = false
// f.peersMap[c.Id] = endPoint
// }
//}
logger.Info.Printf("PoolFactory PassivateObject peer[%v] \n",object.Object)
return nil
}
func (f *PoolFactory) GetEndPoint() EndPoint {
logger.Info.Printf("PoolFactory pullEndPoint peers %v ", f.peersMap)
var keys []string
var selectedKey string
for key := range f.peersMap {
endPoint := f.peersMap[key]
if endPoint.Available {
keys = append(keys, key)
}
selectedKey = key
}
if len(keys) > 0 {
index := rand.Intn(len(keys))
selectedKey = keys[index]
}
return f.peersMap[selectedKey]
}
func (f *PoolFactory) StartCrawlPeers() {
go func() {
f.cron.AddFunc("0 0/1 * * * *", func() {
logger.Info.Printf("PoolFactory StartCrawlPeers peers %v ", f.peersMap)
client := GetClient()
logger.Info.Printf("PoolFactory peers %v ", client)
defer func() {
client.Release()
if err := recover(); err != nil {
logger.Error.Printf("PoolFactory StartCrawlPeers error: %v ", err)
}
}()
addrs := client.GetNodeAddress()
for _, addr := range addrs {
key := generateId(addr)
if _, ok := f.peersMap[key]; !ok {
f.peersMap[key] = EndPoint{
Address: addr,
Available: true,
}
}
}
//检测节点是否上线
for key := range f.peersMap {
endPoint := f.peersMap[key]
if !endPoint.Available {
node := newClient(endPoint.Address)
if node.HeartBeat() == nil {
endPoint.Available = true
f.peersMap[key] = endPoint
}
}
}
})
f.cron.Start()
}()
}
jolestar commented
@zhiqiang-bianjie I cannot find return object call. Please show the code which the error occurred.
Dreamer commented
func GetClient() *Client {
defer func() {
if err := recover(); err != nil {
logger.Error.Println(err)
}
}()
c, err := pool.BorrowObject(ctx)
if err != nil {
logger.Error.Println("GetClient failed,err:",err)
return nil
}
logger.Info.Printf("current available connection:%d", pool.GetNumIdle())
logger.Info.Printf("current used connection:%d", pool.GetNumActive())
return c.(*Client)
}
// release client
func (c *Client) Release() {
err := pool.ReturnObject(ctx, c)
if err != nil {
logger.Info.Println("debug=======================Release err=======================debug")
logger.Error.Println(err.Error())
}
logger.Info.Println("debug=======================Release return=======================debug")
}
jolestar commented
@zhiqiang-bianjie
I can not find out why this error occurs.
This error means your return Object is not created by Pool. Find code to create client directly, such as node := newClient(endPoint.Address)
, and make sure that the client does not call Release.
You can print all create and return Object's pointer address, and make sure they all match.
Dreamer commented
ok,thanks