aboutsummaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
authorMike Crute <mike@crute.us>2021-11-07 18:42:15 -0800
committerMike Crute <mike@crute.us>2021-11-07 18:42:15 -0800
commitdf0e9084397605e3bd10f5aedd9c2bffd6d10e90 (patch)
tree70c56ca38330a816828cd595eaeea96c923318c9 /service
downloadgolib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.tar.bz2
golib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.tar.xz
golib-df0e9084397605e3bd10f5aedd9c2bffd6d10e90.zip
Initial extraction commit
Diffstat (limited to 'service')
-rw-r--r--service/app_runner.go90
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 @@
1package service
2
3import (
4 "context"
5 "os"
6 "os/signal"
7 "sync"
8 "syscall"
9)
10
11type AppRunnerLogger interface {
12 Info(...interface{})
13}
14
15type RunnerFunc func(context.Context, *sync.WaitGroup) error
16
17type 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
27func 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
45func (r *AppRunner) AddJob(f RunnerFunc) {
46 r.jobs = append(r.jobs, f)
47}
48
49func (r *AppRunner) AddBackgroundJob(f RunnerFunc) {
50 r.backgroundJobs = append(r.backgroundJobs, f)
51}
52
53func (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
63func (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}