Add WithTimeout

This commit is contained in:
Vladimir Mihailenco 2020-02-02 14:59:27 +02:00
parent 2df96f7ef0
commit d2e52839ee
4 changed files with 62 additions and 18 deletions

View File

@ -169,6 +169,11 @@ func (opt *Options) init() {
} }
} }
func (opt *Options) clone() *Options {
clone := *opt
return &clone
}
// ParseURL parses an URL into Options that can be used to connect to Redis. // ParseURL parses an URL into Options that can be used to connect to Redis.
func ParseURL(redisURL string) (*Options, error) { func ParseURL(redisURL string) (*Options, error) {
o := &Options{Network: "tcp"} o := &Options{Network: "tcp"}

View File

@ -137,6 +137,29 @@ type baseClient struct {
onClose func() error // hook called when client is closed onClose func() error // hook called when client is closed
} }
func newBaseClient(opt *Options, connPool pool.Pooler) *baseClient {
return &baseClient{
opt: opt,
connPool: connPool,
}
}
func (c *baseClient) clone() *baseClient {
clone := *c
return &clone
}
func (c *baseClient) withTimeout(timeout time.Duration) *baseClient {
opt := c.opt.clone()
opt.ReadTimeout = timeout
opt.WriteTimeout = timeout
clone := c.clone()
clone.opt = opt
return clone
}
func (c *baseClient) String() string { func (c *baseClient) String() string {
return fmt.Sprintf("Redis<%s db:%d>", c.getAddr(), c.opt.DB) return fmt.Sprintf("Redis<%s db:%d>", c.getAddr(), c.opt.DB)
} }
@ -481,7 +504,7 @@ func txPipelineReadQueued(rd *proto.Reader, cmds []Cmder) error {
// underlying connections. It's safe for concurrent use by multiple // underlying connections. It's safe for concurrent use by multiple
// goroutines. // goroutines.
type Client struct { type Client struct {
baseClient *baseClient
cmdable cmdable
hooks hooks
ctx context.Context ctx context.Context
@ -492,10 +515,7 @@ func NewClient(opt *Options) *Client {
opt.init() opt.init()
c := Client{ c := Client{
baseClient: baseClient{ baseClient: newBaseClient(opt, newConnPool(opt)),
opt: opt,
connPool: newConnPool(opt),
},
ctx: context.Background(), ctx: context.Background(),
} }
c.cmdable = c.Process c.cmdable = c.Process
@ -503,6 +523,19 @@ func NewClient(opt *Options) *Client {
return &c return &c
} }
func (c *Client) clone() *Client {
clone := *c
clone.cmdable = clone.Process
clone.hooks.Lock()
return &clone
}
func (c *Client) WithTimeout(timeout time.Duration) *Client {
clone := c.clone()
clone.baseClient = c.baseClient.withTimeout(timeout)
return clone
}
func (c *Client) Context() context.Context { func (c *Client) Context() context.Context {
return c.ctx return c.ctx
} }
@ -511,11 +544,9 @@ func (c *Client) WithContext(ctx context.Context) *Client {
if ctx == nil { if ctx == nil {
panic("nil context") panic("nil context")
} }
clone := *c clone := c.clone()
clone.cmdable = clone.Process
clone.hooks.Lock()
clone.ctx = ctx clone.ctx = ctx
return &clone return clone
} }
func (c *Client) Conn() *Conn { func (c *Client) Conn() *Conn {

View File

@ -59,6 +59,10 @@ var _ = Describe("Client", func() {
client.Close() client.Close()
}) })
It("should Stringer", func() {
Expect(client.String()).To(Equal("Redis<:6380 db:15>"))
})
It("supports WithContext", func() { It("supports WithContext", func() {
c, cancel := context.WithCancel(context.Background()) c, cancel := context.WithCancel(context.Background())
cancel() cancel()
@ -67,8 +71,15 @@ var _ = Describe("Client", func() {
Expect(err).To(MatchError("context canceled")) Expect(err).To(MatchError("context canceled"))
}) })
It("should Stringer", func() { It("supports WithTimeout", func() {
Expect(client.String()).To(Equal("Redis<:6380 db:15>")) err := client.ClientPause(time.Second).Err()
Expect(err).NotTo(HaveOccurred())
err = client.WithTimeout(10 * time.Millisecond).Ping().Err()
Expect(err).To(HaveOccurred())
err = client.Ping().Err()
Expect(err).NotTo(HaveOccurred())
}) })
It("should ping", func() { It("should ping", func() {

View File

@ -94,14 +94,11 @@ func NewFailoverClient(failoverOpt *FailoverOptions) *Client {
} }
c := Client{ c := Client{
baseClient: baseClient{ baseClient: newBaseClient(opt, failover.Pool()),
opt: opt,
connPool: failover.Pool(),
onClose: failover.Close,
},
ctx: context.Background(), ctx: context.Background(),
} }
c.cmdable = c.Process c.cmdable = c.Process
c.onClose = failover.Close
return &c return &c
} }