@@ -33,6 +33,7 @@ import (
33
33
"tailscale.com/derp/derphttp"
34
34
"tailscale.com/tailcfg"
35
35
"tailscale.com/types/key"
36
+ "tailscale.com/util/singleflight"
36
37
37
38
"cdr.dev/slog"
38
39
"github.com/coder/coder/buildinfo"
@@ -46,6 +47,7 @@ import (
46
47
"github.com/coder/coder/coderd/database/dbtype"
47
48
"github.com/coder/coder/coderd/gitauth"
48
49
"github.com/coder/coder/coderd/gitsshkey"
50
+ "github.com/coder/coder/coderd/healthcheck"
49
51
"github.com/coder/coder/coderd/httpapi"
50
52
"github.com/coder/coder/coderd/httpmw"
51
53
"github.com/coder/coder/coderd/metricscache"
@@ -123,7 +125,10 @@ type Options struct {
123
125
TemplateScheduleStore schedule.TemplateScheduleStore
124
126
// AppSigningKey denotes the symmetric key to use for signing app tickets.
125
127
// The key must be 64 bytes long.
126
- AppSigningKey []byte
128
+ AppSigningKey []byte
129
+ HealthcheckFunc func (ctx context.Context ) (* healthcheck.Report , error )
130
+ HealthcheckTimeout time.Duration
131
+ HealthcheckRefresh time.Duration
127
132
128
133
// APIRateLimit is the minutely throughput rate limit per user or ip.
129
134
// Setting a rate limit <0 will disable the rate limiter across the entire
@@ -235,6 +240,19 @@ func New(options *Options) *API {
235
240
if len (options .AppSigningKey ) != 64 {
236
241
panic ("coderd: AppSigningKey must be 64 bytes long" )
237
242
}
243
+ if options .HealthcheckFunc == nil {
244
+ options .HealthcheckFunc = func (ctx context.Context ) (* healthcheck.Report , error ) {
245
+ return healthcheck .Run (ctx , & healthcheck.ReportOptions {
246
+ DERPMap : options .DERPMap .Clone (),
247
+ })
248
+ }
249
+ }
250
+ if options .HealthcheckTimeout == 0 {
251
+ options .HealthcheckTimeout = 30 * time .Second
252
+ }
253
+ if options .HealthcheckRefresh == 0 {
254
+ options .HealthcheckRefresh = 10 * time .Minute
255
+ }
238
256
239
257
siteCacheDir := options .CacheDir
240
258
if siteCacheDir != "" {
@@ -293,6 +311,7 @@ func New(options *Options) *API {
293
311
Auditor : atomic.Pointer [audit.Auditor ]{},
294
312
TemplateScheduleStore : atomic.Pointer [schedule.TemplateScheduleStore ]{},
295
313
Experiments : experiments ,
314
+ healthCheckGroup : & singleflight.Group [string , * healthcheck.Report ]{},
296
315
}
297
316
if options .UpdateCheckOptions != nil {
298
317
api .updateChecker = updatecheck .New (
@@ -718,6 +737,7 @@ func New(options *Options) *API {
718
737
)
719
738
720
739
r .Get ("/coordinator" , api .debugCoordinator )
740
+ r .Get ("/health" , api .debugDeploymentHealth )
721
741
})
722
742
})
723
743
@@ -773,6 +793,8 @@ type API struct {
773
793
// Experiments contains the list of experiments currently enabled.
774
794
// This is used to gate features that are not yet ready for production.
775
795
Experiments codersdk.Experiments
796
+
797
+ healthCheckGroup * singleflight.Group [string , * healthcheck.Report ]
776
798
}
777
799
778
800
// Close waits for all WebSocket connections to drain before returning.
0 commit comments