MCPcopy Index your code
hub / github.com/coder/coder / NewAppHealthReporterWithClock

Function NewAppHealthReporterWithClock

agent/apphealth.go:31–165  ·  view source on GitHub ↗

NewAppHealthReporterWithClock is only called directly by test code. Product code should call NewAppHealthReporter.

(
	logger slog.Logger,
	apps []codersdk.WorkspaceApp,
	postWorkspaceAgentAppHealth PostWorkspaceAgentAppHealth,
	clk quartz.Clock,
)

Source from the content-addressed store, hash-verified

29// NewAppHealthReporterWithClock is only called directly by test code. Product code should call
30// NewAppHealthReporter.
31func NewAppHealthReporterWithClock(
32 logger slog.Logger,
33 apps []codersdk.WorkspaceApp,
34 postWorkspaceAgentAppHealth PostWorkspaceAgentAppHealth,
35 clk quartz.Clock,
36) WorkspaceAppHealthReporter {
37 logger = logger.Named("apphealth")
38
39 return func(ctx context.Context) {
40 ctx, cancel := context.WithCancel(ctx)
41 defer cancel()
42
43 // no need to run this loop if no apps for this workspace.
44 if len(apps) == 0 {
45 return
46 }
47
48 hasHealthchecksEnabled := false
49 health := make(map[uuid.UUID]codersdk.WorkspaceAppHealth, 0)
50 for _, app := range apps {
51 if app.Health == codersdk.WorkspaceAppHealthDisabled {
52 continue
53 }
54 health[app.ID] = app.Health
55 hasHealthchecksEnabled = true
56 }
57
58 // no need to run this loop if no health checks are configured.
59 if !hasHealthchecksEnabled {
60 return
61 }
62
63 // run a ticker for each app health check.
64 var mu sync.RWMutex
65 failures := make(map[uuid.UUID]int, 0)
66 client := &http.Client{}
67 for _, nextApp := range apps {
68 if !shouldStartTicker(nextApp) {
69 continue
70 }
71 app := nextApp
72 go func() {
73 _ = clk.TickerFunc(ctx, time.Duration(app.Healthcheck.Interval)*time.Second, func() error {
74 // We time out at the healthcheck interval to prevent getting too backed up, but
75 // set it 1ms early so that it's not simultaneous with the next tick in testing,
76 // which makes the test easier to understand.
77 //
78 // It would be idiomatic to use the http.Client.Timeout or a context.WithTimeout,
79 // but we are passing this off to the native http library, which is not aware
80 // of the clock library we are using. That means in testing, with a mock clock
81 // it will compare mocked times with real times, and we will get strange results.
82 // So, we just implement the timeout as a context we cancel with an AfterFunc
83 reqCtx, reqCancel := context.WithCancel(ctx)
84 timeout := clk.AfterFunc(
85 time.Duration(app.Healthcheck.Interval)*time.Second-time.Millisecond,
86 reqCancel,
87 "timeout", app.Slug)
88 defer timeout.Stop()

Callers 2

setupAppReporterFunction · 0.92

Calls 14

shouldStartTickerFunction · 0.85
copyHealthFunction · 0.85
healthChangedFunction · 0.85
NamedMethod · 0.80
DurationMethod · 0.80
StopMethod · 0.65
DoMethod · 0.65
CloseMethod · 0.65
WaitMethod · 0.65
ErrorfMethod · 0.45
LockMethod · 0.45
UnlockMethod · 0.45

Tested by 1

setupAppReporterFunction · 0.74