MCPcopy Create free account
hub / github.com/coder/coder / runOnce

Method runOnce

enterprise/coderd/proxyhealth/proxyhealth.go:218–385  ·  view source on GitHub ↗

runOnce runs the health check for all workspace proxies. If there is an unexpected error, an error is returned. Expected errors will mark a proxy as unreachable.

(ctx context.Context, now time.Time)

Source from the content-addressed store, hash-verified

216// unexpected error, an error is returned. Expected errors will mark a proxy as
217// unreachable.
218func (p *ProxyHealth) runOnce(ctx context.Context, now time.Time) (map[uuid.UUID]ProxyStatus, error) {
219 // Record from the given time.
220 defer func() { p.healthCheckDuration.Observe(time.Since(now).Seconds()) }()
221
222 //nolint:gocritic // Proxy health is a system service.
223 proxies, err := p.db.GetWorkspaceProxies(dbauthz.AsSystemRestricted(ctx))
224 if err != nil {
225 return nil, xerrors.Errorf("get workspace proxies: %w", err)
226 }
227
228 // Just use a mutex to protect map writes.
229 var statusMu sync.Mutex
230 proxyStatus := map[uuid.UUID]ProxyStatus{}
231
232 grp, gctx := errgroup.WithContext(ctx)
233 // Arbitrary parallelism limit.
234 grp.SetLimit(5)
235
236 for _, proxy := range proxies {
237 if proxy.Deleted {
238 // Ignore deleted proxies.
239 continue
240 }
241 // Each proxy needs to have a status set. Make a local copy for the
242 // call to be run async.
243 status := ProxyStatus{
244 Proxy: proxy,
245 CheckedAt: now,
246 Status: Unknown,
247 }
248
249 grp.Go(func() error {
250 if proxy.Url == "" {
251 // Empty URL means the proxy has not registered yet.
252 // When the proxy is started, it will update the url.
253 statusMu.Lock()
254 defer statusMu.Unlock()
255 p.healthCheckResults.WithLabelValues(prometheusmetrics.VectorOperationSet, 0, proxy.ID.String())
256 status.Status = Unregistered
257 proxyStatus[proxy.ID] = status
258 return nil
259 }
260
261 // Try to hit the healthz-report endpoint for a comprehensive health check.
262 reqURL := fmt.Sprintf("%s/healthz-report", strings.TrimSuffix(proxy.Url, "/"))
263 req, err := http.NewRequestWithContext(gctx, http.MethodGet, reqURL, nil)
264 if err != nil {
265 return xerrors.Errorf("new request: %w", err)
266 }
267 req = req.WithContext(gctx)
268
269 resp, err := p.client.Do(req)
270 if err == nil {
271 defer resp.Body.Close()
272 }
273 // A switch statement felt easier to categorize the different cases than
274 // if else statements or nested if statements.
275 switch {

Callers 2

RunMethod · 0.95
ForceUpdateMethod · 0.95

Calls 15

AsSystemRestrictedFunction · 0.92
ExpectJSONMimeFunction · 0.92
ReadBodyAsErrorFunction · 0.92
ConvertAppHostForCSPFunction · 0.92
WithContextMethod · 0.80
GoMethod · 0.80
WithLabelValuesMethod · 0.80
WriteStringMethod · 0.80
AsMethod · 0.80
CommitMethod · 0.80
GetWorkspaceProxiesMethod · 0.65
DoMethod · 0.65

Tested by

no test coverage detected