Beispiel #1
0
func (c *ClusterClient) Process(cmd Cmder) error {
	slot, node, err := c.cmdSlotAndNode(cmd)
	if err != nil {
		cmd.setErr(err)
		return err
	}

	var ask bool
	for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ {
		if attempt > 0 {
			cmd.reset()
		}

		if ask {
			pipe := node.Client.Pipeline()
			pipe.Process(NewCmd("ASKING"))
			pipe.Process(cmd)
			_, _ = pipe.Exec()
			pipe.Close()
			ask = false
		} else {
			node.Client.Process(cmd)
		}

		// If there is no (real) error, we are done!
		err := cmd.Err()
		if err == nil {
			return nil
		}

		// On network errors try random node.
		if errors.IsRetryable(err) {
			node, err = c.randomNode()
			continue
		}

		var moved bool
		var addr string
		moved, ask, addr = errors.IsMoved(err)
		if moved || ask {
			master, _ := c.slotMasterNode(slot)
			if moved && (master == nil || master.Client.getAddr() != addr) {
				c.lazyReloadSlots()
			}

			node, err = c.nodeByAddr(addr)
			if err != nil {
				cmd.setErr(err)
				return err
			}
			continue
		}

		break
	}

	return cmd.Err()
}
Beispiel #2
0
func (c *ClusterClient) execClusterCmds(
	cn *pool.Conn, cmds []Cmder, failedCmds map[*clusterNode][]Cmder,
) (map[*clusterNode][]Cmder, error) {
	if err := writeCmd(cn, cmds...); err != nil {
		setCmdsErr(cmds, err)
		return failedCmds, err
	}

	var retErr error
	setRetErr := func(err error) {
		if retErr == nil {
			retErr = err
		}
	}

	for i, cmd := range cmds {
		err := cmd.readReply(cn)
		if err == nil {
			continue
		}
		if errors.IsNetwork(err) {
			cmd.reset()
			failedCmds[nil] = append(failedCmds[nil], cmds[i:]...)
			break
		} else if moved, ask, addr := errors.IsMoved(err); moved {
			c.lazyReloadSlots()
			cmd.reset()
			node, err := c.nodeByAddr(addr)
			if err != nil {
				setRetErr(err)
				continue
			}
			failedCmds[node] = append(failedCmds[node], cmd)
		} else if ask {
			cmd.reset()
			node, err := c.nodeByAddr(addr)
			if err != nil {
				setRetErr(err)
				continue
			}
			failedCmds[node] = append(failedCmds[node], NewCmd("ASKING"), cmd)
		} else {
			setRetErr(err)
		}
	}

	return failedCmds, retErr
}