...
Source file
src/tawesoft.co.uk/go/grace/grace.go
Documentation:
src/tawesoft.co.uk/go/grace/grace.go
1 package grace
2
3 import (
4 "context"
5 "os"
6 "os/signal"
7 "sync"
8 "syscall"
9 )
10
11
12 type Process interface {
13
14
15
16
17 Start(done func()) error
18
19
20
21 Stop(context.Context) error
22 }
23
24 func shutdown(ctx context.Context, processes []Process) []error {
25 var errors []error
26
27 for _, process := range processes {
28 if err := process.Stop(ctx); err != nil {
29 errors = append(errors, err)
30 }
31 }
32
33 return errors
34 }
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 func Run(ctx context.Context, processes []Process, signals []os.Signal) (os.Signal, []error, error) {
54
55 var wg sync.WaitGroup
56 closechan := make(chan struct{sig os.Signal; errs []error}, 1)
57
58 donefn := func() {
59 wg.Done()
60 }
61
62
63 for i, process := range processes {
64 err := process.Start(donefn)
65 if err != nil {
66 errors := shutdown(ctx, processes[0:i])
67 wg.Wait()
68 return syscall.Signal(0), errors, err
69 }
70 wg.Add(1)
71 }
72
73
74 go func(ctx context.Context) {
75
76 var result os.Signal
77 sigchan := make(chan os.Signal, 1)
78 signal.Notify(sigchan, signals...)
79
80 select {
81 case result = <- sigchan:
82 case <- ctx.Done():
83 }
84
85 errors := shutdown(ctx, processes)
86 wg.Wait()
87 closechan <- struct{sig os.Signal; errs []error}{result, errors}
88 }(ctx)
89
90
91 result := <- closechan
92 return result.sig, result.errs, nil
93 }
94
View as plain text