runLoop attempts to start the agent in a retry loop. Coder may be offline temporarily, a connection issue may be happening, but regardless after the intermittent failure, you'll want the agent to reconnect.
()
| 493 | // may be happening, but regardless after the intermittent |
| 494 | // failure, you'll want the agent to reconnect. |
| 495 | func (a *agent) runLoop() { |
| 496 | // need to keep retrying up to the hardCtx so that we can send graceful shutdown-related |
| 497 | // messages. |
| 498 | ctx := a.hardCtx |
| 499 | defer a.logger.Info(ctx, "agent main loop exited") |
| 500 | for retrier := retry.New(100*time.Millisecond, 10*time.Second); retrier.Wait(ctx); { |
| 501 | a.logger.Info(ctx, "connecting to coderd") |
| 502 | err := a.run() |
| 503 | if err == nil { |
| 504 | continue |
| 505 | } |
| 506 | if ctx.Err() != nil { |
| 507 | // Context canceled errors may come from websocket pings, so we |
| 508 | // don't want to use `errors.Is(err, context.Canceled)` here. |
| 509 | a.logger.Warn(ctx, "runLoop exited with error", slog.Error(ctx.Err())) |
| 510 | return |
| 511 | } |
| 512 | if a.isClosed() { |
| 513 | a.logger.Warn(ctx, "runLoop exited because agent is closed") |
| 514 | return |
| 515 | } |
| 516 | if errors.Is(err, io.EOF) { |
| 517 | a.logger.Info(ctx, "disconnected from coderd", |
| 518 | codersdk.ConnectionDirectionServerToAgent.SlogField(), |
| 519 | codersdk.DisconnectReasonNetworkError.SlogField(), |
| 520 | codersdk.DisconnectReasonNetworkError.SlogExpectedField(), |
| 521 | codersdk.DisconnectInitiatorNetwork.SlogField(), |
| 522 | ) |
| 523 | continue |
| 524 | } |
| 525 | a.logger.Warn(ctx, "run exited with error", slog.Error(err)) |
| 526 | } |
| 527 | } |
| 528 | |
| 529 | func (a *agent) collectMetadata(ctx context.Context, md codersdk.WorkspaceAgentMetadataDescription, now time.Time) *codersdk.WorkspaceAgentMetadataResult { |
| 530 | var out bytes.Buffer |