diff options
author | Mike Crute <mike@crute.us> | 2021-11-07 18:42:15 -0800 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2021-11-07 18:42:15 -0800 |
commit | df0e9084397605e3bd10f5aedd9c2bffd6d10e90 (patch) | |
tree | 70c56ca38330a816828cd595eaeea96c923318c9 /service | |
download | golib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.tar.bz2 golib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.tar.xz golib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.zip |
Initial extraction commit
Diffstat (limited to 'service')
-rw-r--r-- | service/app_runner.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/service/app_runner.go b/service/app_runner.go new file mode 100644 index 0000000..2aecf52 --- /dev/null +++ b/service/app_runner.go | |||
@@ -0,0 +1,90 @@ | |||
1 | package service | ||
2 | |||
3 | import ( | ||
4 | "context" | ||
5 | "os" | ||
6 | "os/signal" | ||
7 | "sync" | ||
8 | "syscall" | ||
9 | ) | ||
10 | |||
11 | type AppRunnerLogger interface { | ||
12 | Info(...interface{}) | ||
13 | } | ||
14 | |||
15 | type RunnerFunc func(context.Context, *sync.WaitGroup) error | ||
16 | |||
17 | type AppRunner struct { | ||
18 | Logger AppRunnerLogger | ||
19 | jobs []RunnerFunc | ||
20 | backgroundJobs []RunnerFunc | ||
21 | wg *sync.WaitGroup | ||
22 | sigs chan os.Signal | ||
23 | ctx context.Context | ||
24 | ctxCancel context.CancelFunc | ||
25 | } | ||
26 | |||
27 | func NewAppRunner(ctx context.Context, logger AppRunnerLogger) *AppRunner { | ||
28 | r := &AppRunner{ | ||
29 | jobs: []RunnerFunc{}, | ||
30 | backgroundJobs: []RunnerFunc{}, | ||
31 | wg: &sync.WaitGroup{}, | ||
32 | sigs: make(chan os.Signal), | ||
33 | Logger: logger, | ||
34 | } | ||
35 | |||
36 | r.ctx, r.ctxCancel = context.WithCancel(ctx) | ||
37 | |||
38 | signal.Notify(r.sigs, os.Interrupt) | ||
39 | signal.Notify(r.sigs, os.Kill) | ||
40 | signal.Notify(r.sigs, syscall.SIGTERM) | ||
41 | |||
42 | return r | ||
43 | } | ||
44 | |||
45 | func (r *AppRunner) AddJob(f RunnerFunc) { | ||
46 | r.jobs = append(r.jobs, f) | ||
47 | } | ||
48 | |||
49 | func (r *AppRunner) AddBackgroundJob(f RunnerFunc) { | ||
50 | r.backgroundJobs = append(r.backgroundJobs, f) | ||
51 | } | ||
52 | |||
53 | func (r *AppRunner) goRunPanic(f func(context.Context, *sync.WaitGroup) error) { | ||
54 | errs := make(chan error) | ||
55 | go func() { errs <- f(r.ctx, r.wg) }() | ||
56 | select { | ||
57 | case e := <-errs: | ||
58 | panic(e) | ||
59 | default: | ||
60 | } | ||
61 | } | ||
62 | |||
63 | func (r *AppRunner) RunForever(enableBg bool) { | ||
64 | for _, f := range r.jobs { | ||
65 | r.goRunPanic(f) | ||
66 | } | ||
67 | |||
68 | if enableBg { | ||
69 | r.Logger.Info("Starting background jobs") | ||
70 | for _, f := range r.backgroundJobs { | ||
71 | r.goRunPanic(f) | ||
72 | } | ||
73 | } else { | ||
74 | r.Logger.Info("Background jobs not enabled") | ||
75 | } | ||
76 | |||
77 | // go run foreground | ||
78 | // go run background if enabled | ||
79 | select { | ||
80 | case <-r.sigs: | ||
81 | r.Logger.Info("Shutting down main app context") | ||
82 | r.ctxCancel() | ||
83 | |||
84 | r.Logger.Info("Waiting for jobs to terminate") | ||
85 | r.wg.Wait() | ||
86 | |||
87 | r.Logger.Info("Shutdown completed") | ||
88 | return | ||
89 | } | ||
90 | } | ||