resetTransportAndUnlock unconditionally connects the addrConn. ac.mu must be held by the caller, and this function will guarantee it is released.
()
| 1324 | // |
| 1325 | // ac.mu must be held by the caller, and this function will guarantee it is released. |
| 1326 | func (ac *addrConn) resetTransportAndUnlock() { |
| 1327 | acCtx := ac.ctx |
| 1328 | if acCtx.Err() != nil { |
| 1329 | ac.mu.Unlock() |
| 1330 | return |
| 1331 | } |
| 1332 | |
| 1333 | addrs := ac.addrs |
| 1334 | backoffFor := ac.dopts.bs.Backoff(ac.backoffIdx) |
| 1335 | // This will be the duration that dial gets to finish. |
| 1336 | dialDuration := minConnectTimeout |
| 1337 | if ac.dopts.minConnectTimeout != nil { |
| 1338 | dialDuration = ac.dopts.minConnectTimeout() |
| 1339 | } |
| 1340 | |
| 1341 | if dialDuration < backoffFor { |
| 1342 | // Give dial more time as we keep failing to connect. |
| 1343 | dialDuration = backoffFor |
| 1344 | } |
| 1345 | // We can potentially spend all the time trying the first address, and |
| 1346 | // if the server accepts the connection and then hangs, the following |
| 1347 | // addresses will never be tried. |
| 1348 | // |
| 1349 | // The spec doesn't mention what should be done for multiple addresses. |
| 1350 | // https://github.com/grpc/grpc/blob/master/doc/connection-backoff.md#proposed-backoff-algorithm |
| 1351 | connectDeadline := time.Now().Add(dialDuration) |
| 1352 | |
| 1353 | ac.updateConnectivityState(connectivity.Connecting, nil) |
| 1354 | ac.mu.Unlock() |
| 1355 | |
| 1356 | if err := ac.tryAllAddrs(acCtx, addrs, connectDeadline); err != nil { |
| 1357 | if !errors.Is(err, context.Canceled) { |
| 1358 | connectionAttemptsFailedMetric.Record(ac.cc.metricsRecorderList, 1, ac.cc.target, ac.backendServiceLabel, ac.localityLabel) |
| 1359 | } else { |
| 1360 | if logger.V(2) { |
| 1361 | // This records cancelled connection attempts which can be later |
| 1362 | // replaced by a metric. |
| 1363 | logger.Infof("Context cancellation detected; not recording this as a failed connection attempt.") |
| 1364 | } |
| 1365 | } |
| 1366 | // TODO: #7534 - Move re-resolution requests into the pick_first LB policy |
| 1367 | // to ensure one resolution request per pass instead of per subconn failure. |
| 1368 | ac.cc.resolveNow(resolver.ResolveNowOptions{}) |
| 1369 | ac.mu.Lock() |
| 1370 | if acCtx.Err() != nil { |
| 1371 | // addrConn was torn down. |
| 1372 | ac.mu.Unlock() |
| 1373 | return |
| 1374 | } |
| 1375 | // After exhausting all addresses, the addrConn enters |
| 1376 | // TRANSIENT_FAILURE. |
| 1377 | ac.updateConnectivityState(connectivity.TransientFailure, err) |
| 1378 | |
| 1379 | // Backoff. |
| 1380 | b := ac.resetBackoff |
| 1381 | ac.mu.Unlock() |
| 1382 | |
| 1383 | timer := time.NewTimer(backoffFor) |
no test coverage detected