// Exec always returns list of commands and error of the first failed // command if any. func (pipe *RingPipeline) Exec() (cmds []Cmder, retErr error) { if pipe.closed { return nil, pool.ErrClosed } if len(pipe.cmds) == 0 { return pipe.cmds, nil } cmds = pipe.cmds pipe.cmds = make([]Cmder, 0, 10) cmdsMap := make(map[string][]Cmder) for _, cmd := range cmds { name := pipe.ring.hash.Get(hashtag.Key(cmd.clusterKey())) if name == "" { cmd.setErr(errRingShardsDown) if retErr == nil { retErr = errRingShardsDown } continue } cmdsMap[name] = append(cmdsMap[name], cmd) } for i := 0; i <= pipe.ring.opt.MaxRetries; i++ { failedCmdsMap := make(map[string][]Cmder) for name, cmds := range cmdsMap { client := pipe.ring.shards[name].Client cn, err := client.conn() if err != nil { setCmdsErr(cmds, err) if retErr == nil { retErr = err } continue } if i > 0 { resetCmds(cmds) } failedCmds, err := execCmds(cn, cmds) client.putConn(cn, err, false) if err != nil && retErr == nil { retErr = err } if len(failedCmds) > 0 { failedCmdsMap[name] = failedCmds } } if len(failedCmdsMap) == 0 { break } cmdsMap = failedCmdsMap } return cmds, retErr }
func (ring *Ring) getClient(key string) (*Client, error) { ring.mx.RLock() if ring.closed { return nil, pool.ErrClosed } name := ring.hash.Get(hashtag.Key(key)) if name == "" { ring.mx.RUnlock() return nil, errRingShardsDown } cl := ring.shards[name].Client ring.mx.RUnlock() return cl, nil }