// Return is used to return resource to pool group func (p *Group) Return(ctx context.Context, res Resource, forceClose bool) error { if res == nil { log.Errorf(ctx, "Return pool conn is null") return nil } pool, err := p.findPool(res.Address()) if err != nil { log.Errorf(ctx, "Return pool conn can't found pool to them and close conn, address: %s", res.Address()) res.Close() } pool.Put(ctx, res, forceClose) return nil }
func (r *ResourcePool) closeConn(ctx context.Context, resource Resource) { if resource == nil { return } err := resource.RawClose() if err != nil { log.Errorf(ctx, "Close connection but failured, address: %s", r.address) } log.Infof(ctx, "Close resource: %s", resource.Address()) }
// Get is used to get resource form group pool func (p *Group) Get(ctx context.Context) (Resource, error) { pool, _, err := p.selectPool(ctx) if err == nil { return nil, err } res, err := pool.Get(ctx) if err != nil { log.Errorf(ctx, "Select pool failure, error: %v", err) return nil, err } log.Infof(ctx, "Selected pool %s with %d\n", res.Address()) return res, nil }
// enqueue is used to do real enqueue op func (r *ResourcePool) enqueue(ctx context.Context, res Resource) { if r.address != res.Address() { log.Errorf(ctx, "FATAL: Conn %s back to wrong pool %s\n", r.address, res.Address()) } start := time.Now() log.Infof(ctx, "Start enqueue, address: %s, av-size: %d\n", res.Address(), len(r.resources)) select { case r.resources <- resourceWrapper{res, time.Now()}: log.Infof(ctx, "Put resource back, address: %s, av-size: %d, waste-time: %d\n", res.Address(), len(r.resources), time.Now().Sub(start).Nanoseconds()) return default: log.Warningf(ctx, "Put resource back failure, because full close it, address: %s, waste-time: %d\n", res.Address(), len(r.resources)) r.closeConn(ctx, res) } }
// Get resource from pool func (r *ResourcePool) get(ctx context.Context, wait bool) (Resource, error) { select { case <-ctx.Done(): return nil, ErrTimeout default: } var ( wrapper resourceWrapper err error ) start := time.Now() for { select { case wrapper = <-r.resources: if time.Now().Sub(wrapper.timeUsed) >= r.idleTimeout { log.Warningf(ctx, "Get idle timeout resource, address: %s, av-size: %d, waste-time: %d\n", wrapper.resource.Address(), len(r.resources), time.Now().Sub(start).Nanoseconds()) r.closeConn(ctx, wrapper.resource) continue } log.Infof(ctx, "Get resouce from pool success, address: %v, av-size: %d, waste-time: %d\n", wrapper.resource.Address(), len(r.resources), time.Now().Sub(start).Nanoseconds()) return wrapper.resource, nil default: log.Warningf(ctx, "Have not enough resource in pool, start create resource, address: %s, av-size: %d\n", r.address, len(r.resources)) var res Resource if res, err = r.factory(); err != nil { log.Errorf(ctx, "create resource failure, error: %v", err) return nil, err } log.Infof(ctx, "Create new resource successed, address: %s", res.Address()) r.enqueue(ctx, res) log.Infof(ctx, "New resource back to queue sucessed, address: %s, av-size: %d", res.Address(), len(r.resources)) continue } } }