Repository navigation
Expand file tree
/
Copy pathexample_bootstrap_test.go
More file actions
73 lines (58 loc) · 1.91 KB
/
Copy pathexample_bootstrap_test.go
File metadata and controls
73 lines (58 loc) · 1.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package bootstrap_test
import (
"context"
"fmt"
"log/slog"
"sync"
"time"
"github.com/tecnickcom/nurago/pkg/bootstrap"
"github.com/tecnickcom/nurago/pkg/metrics"
)
func ExampleBootstrap() {
// A real service lets Bootstrap block on SIGINT or SIGTERM. The example
// cancels the context from inside the bind function so it terminates.
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()
var wg sync.WaitGroup
shutdown := make(chan struct{})
// BindFunc is where the application registers its own components: HTTP
// servers, database connections, background workers. It receives the
// application context, logger, and metrics client already wired.
bindFn := func(ctx context.Context, _ *slog.Logger, mtr metrics.Client) error {
worker(ctx, &wg, shutdown)
mtr.IncErrorCounter("startup", "bind", "0")
fmt.Println("application wired")
// Stand-in for the signal that would normally end the process.
cancel()
return nil
}
// Bootstrap returns once every registered dependant has finished, or
// with an error wrapping ErrShutdownTimeout if they exceed the budget.
err := bootstrap.Bootstrap(
bindFn,
bootstrap.WithContext(ctx),
bootstrap.WithShutdownSignalChan(shutdown),
bootstrap.WithShutdownWaitGroup(&wg),
bootstrap.WithShutdownTimeout(5*time.Second),
bootstrap.WithCreateMetricsClientFunc(func() (metrics.Client, error) {
return &metrics.Default{}, nil
}),
)
fmt.Println("bootstrap returned:", err)
// Output:
// application wired
// worker stopped
// bootstrap returned: <nil>
}
// worker is a background task participating in graceful shutdown: it joins the
// wait group so Bootstrap blocks for it, and stops when either the shutdown
// channel closes or the context is canceled.
func worker(ctx context.Context, wg *sync.WaitGroup, shutdown chan struct{}) {
wg.Go(func() {
select {
case <-shutdown:
case <-ctx.Done():
}
fmt.Println("worker stopped")
})
}