// 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 } } }
// 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) } }