gomodule/redigo

Add DoWithCancel

Open

#351 创建于 2018年6月27日

在 GitHub 查看
 (1 评论) (5 反应) (0 负责人)Go (7,782 star) (1,116 fork)batch import
EnhancementHelp wanted

描述

Add DoWithCancel helper function after the Redis CLIENT UNBLOCK command is released.

// DoWithCancel executes cmd with args. If the context is canceled, then
// DoWithCancel unblocks c by executing the CLIENT UNBLOCK command using a
// connection returned from the get function.  Example:
//
//  result, err := redis.Values(redis.DoWithCancel(c, ctx, pool.Get, "BRPOP", "key", 0))
func DoWithCancel(c Conn, ctx context.Context, get func() Conn, cmd string, args ...interface{}) (interface{}, error) {
	id, err := redis.Int(redis.Do("CLIENT", "ID"))
	if err != nil {
		return err
	}
	stop := make(chan struct{})
	wait := make(chan struct{})

	go func() {
		defer close(wait)
		select {
		case <-stop:
		case <-ctx.Done():
                          // TODO: avoid deadlock. If argument c is from pool with Wait = true and the get argument
                         // is the Get() method from that same pool, then the following line can cause a deadlock.
			c := get()
			defer c.Close()
			_, err := c.Do("CLIENT", "UNBLOCK", id)
			// TODO: handle error, possibly by closing the network connection on argument c
		}
	}()

	r, err := c.Do(cmd, args...)
	close(stop)
	<-wait
	return r, err
}

To reduce extra roundtrips to the server, cache the result fo the CLIENT ID command in the low-level connection.

func (c *conn) DoWithTimeout(readTimeout time.Duration, cmd string, args ...interface{}) (interface{}, error) {
    ...
    isClientIDCmd := cmd == "CLIENT" && len(args) == 1 && args[0] == "ID" 
    if isClientIDCmd && c.clientID != nil {
        return c.clientID, nil
    }
    ...
    if isClientIDCmd && err == nil {
        c.clientID = reply
    }
    ...
}

EDIT: An alternative to caching the client ID in the low-level connection is to pipeline CLIENT ID with the application's command. This approach localizes the implementation to this one function and should have little impact on performance.

贡献者指南