(ctx context.Context, cmd Cmder)
| 1233 | } |
| 1234 | |
| 1235 | func (c *ClusterClient) process(ctx context.Context, cmd Cmder) error { |
| 1236 | slot := c.cmdSlot(cmd, -1) |
| 1237 | var node *clusterNode |
| 1238 | var moved bool |
| 1239 | var ask bool |
| 1240 | var lastErr error |
| 1241 | for attempt := 0; attempt <= c.opt.MaxRedirects; attempt++ { |
| 1242 | // MOVED and ASK responses are not transient errors that require retry delay; they |
| 1243 | // should be attempted immediately. |
| 1244 | if attempt > 0 && !moved && !ask { |
| 1245 | if err := internal.Sleep(ctx, c.retryBackoff(attempt)); err != nil { |
| 1246 | return err |
| 1247 | } |
| 1248 | } |
| 1249 | |
| 1250 | if node == nil { |
| 1251 | var err error |
| 1252 | if !c.opt.DisableRoutingPolicies && c.opt.ShardPicker != nil { |
| 1253 | node, err = c.cmdNodeWithShardPicker(ctx, cmd.Name(), slot, c.opt.ShardPicker) |
| 1254 | } else { |
| 1255 | node, err = c.cmdNode(ctx, cmd.Name(), slot) |
| 1256 | } |
| 1257 | if err != nil { |
| 1258 | return err |
| 1259 | } |
| 1260 | } |
| 1261 | |
| 1262 | if ask { |
| 1263 | ask = false |
| 1264 | pipe := node.Client.Pipeline() |
| 1265 | _ = pipe.Process(ctx, NewCmd(ctx, "asking")) |
| 1266 | _ = pipe.Process(ctx, cmd) |
| 1267 | _, lastErr = pipe.Exec(ctx) |
| 1268 | } else { |
| 1269 | if !c.opt.DisableRoutingPolicies { |
| 1270 | lastErr = c.routeAndRun(ctx, cmd, node) |
| 1271 | } else { |
| 1272 | lastErr = node.Client.Process(ctx, cmd) |
| 1273 | } |
| 1274 | } |
| 1275 | |
| 1276 | // If there is no error - we are done. |
| 1277 | if lastErr == nil { |
| 1278 | return nil |
| 1279 | } |
| 1280 | if isReadOnly := isReadOnlyError(lastErr); isReadOnly || lastErr == pool.ErrClosed { |
| 1281 | if isReadOnly { |
| 1282 | c.state.LazyReload() |
| 1283 | } |
| 1284 | node = nil |
| 1285 | continue |
| 1286 | } |
| 1287 | |
| 1288 | // If slave is loading - pick another node. |
| 1289 | if c.opt.ReadOnly && isLoadingError(lastErr) { |
| 1290 | node.MarkAsFailing() |
| 1291 | node = nil |
| 1292 | continue |
nothing calls this directly
no test coverage detected