reconnect asynchronously calls replicatorConnectFn until successful, or times out trying. Retry loop can be stopped by cancelling ctx
()
| 242 | |
| 243 | // reconnect asynchronously calls replicatorConnectFn until successful, or times out trying. Retry loop can be stopped by cancelling ctx |
| 244 | func (arc *activeReplicatorCommon) reconnect() { |
| 245 | arc.reconnectActive.Set(true) |
| 246 | go func() { |
| 247 | base.DebugfCtx(arc.ctx, base.KeyReplicate, "starting reconnector") |
| 248 | defer func() { |
| 249 | arc.reconnectActive.Set(false) |
| 250 | }() |
| 251 | |
| 252 | initialReconnectInterval := defaultInitialReconnectInterval |
| 253 | if arc.config.InitialReconnectInterval != 0 { |
| 254 | initialReconnectInterval = arc.config.InitialReconnectInterval |
| 255 | } |
| 256 | maxReconnectInterval := defaultMaxReconnectInterval |
| 257 | if arc.config.MaxReconnectInterval != 0 { |
| 258 | maxReconnectInterval = arc.config.MaxReconnectInterval |
| 259 | } |
| 260 | |
| 261 | // ctx causes the retry loop to stop if cancelled |
| 262 | ctx := arc.ctx |
| 263 | |
| 264 | // if a reconnect timeout is set, we'll wrap the existing so both can stop the retry loop |
| 265 | var deadlineCancel context.CancelFunc |
| 266 | if arc.config.TotalReconnectTimeout != 0 { |
| 267 | ctx, deadlineCancel = context.WithDeadline(ctx, time.Now().Add(arc.config.TotalReconnectTimeout)) |
| 268 | } |
| 269 | |
| 270 | sleeperFunc := base.SleeperFuncCtx( |
| 271 | base.CreateIndefiniteMaxDoublingSleeperFunc( |
| 272 | int(initialReconnectInterval.Milliseconds()), |
| 273 | int(maxReconnectInterval.Milliseconds())), |
| 274 | ctx) |
| 275 | |
| 276 | retryFunc := func() (shouldRetry bool, err error, _ interface{}) { |
| 277 | // check before and after acquiring lock to make sure to exit early if ActiveReplicatorCommon.Stop() was called. |
| 278 | if ctx.Err() != nil { |
| 279 | return false, ctx.Err(), nil |
| 280 | } |
| 281 | |
| 282 | arc.lock.Lock() |
| 283 | defer arc.lock.Unlock() |
| 284 | |
| 285 | if ctx.Err() != nil { |
| 286 | return false, ctx.Err(), nil |
| 287 | } |
| 288 | |
| 289 | base.DebugfCtx(arc.ctx, base.KeyReplicate, "Attempting to reconnect replicator %s", arc.config.ID) |
| 290 | |
| 291 | // preserve lastError from the previous connect attempt |
| 292 | arc.setState(ReplicationStateReconnecting) |
| 293 | |
| 294 | // disconnect no-ops if nothing is active, but will close any checkpointer processes, blip contexts, etc, if active. |
| 295 | base.TracefCtx(arc.ctx, base.KeyReplicate, "calling disconnect from reconnect") |
| 296 | err = arc._disconnect() |
| 297 | if err != nil { |
| 298 | base.InfofCtx(arc.ctx, base.KeyReplicate, "error stopping replicator on reconnect: %v", err) |
| 299 | } |
| 300 | |
| 301 | // set lastError, but don't set an error state inside the reconnect loop |
no test coverage detected