lib/db: Make database GC a service, stop on Stop() (#6518)

This makes the GC runner a service that will stop fairly quickly when
told to.

As a bonus, STTRACE=app will print the service tree on the way out,
including any errors they've flagged.
This commit is contained in:
Jakob Borg
2020-04-12 10:26:57 +02:00
committed by GitHub
parent 046bbdfbd4
commit 0e67c036bb
3 changed files with 73 additions and 12 deletions
+4
View File
@@ -13,3 +13,7 @@ import (
var (
l = logger.DefaultLogger.NewFacility("app", "Main run facility")
)
func shouldDebug() bool {
return l.ShouldDebug("app")
}
+41
View File
@@ -12,7 +12,9 @@ import (
"fmt"
"io"
"net/http"
"os"
"runtime"
"sort"
"strings"
"sync"
"time"
@@ -126,6 +128,7 @@ func (a *App) startup() error {
},
PassThroughPanics: true,
})
a.mainService.Add(a.ll)
a.mainService.ServeBackground()
if a.opts.AuditWriter != nil {
@@ -371,6 +374,10 @@ func (a *App) startup() error {
func (a *App) run() {
<-a.stop
if shouldDebug() {
l.Debugln("Services before stop:")
printServiceTree(os.Stdout, a.mainService, 0)
}
a.mainService.Stop()
done := make(chan struct{})
@@ -475,3 +482,37 @@ func (e *controller) Shutdown() {
func (e *controller) ExitUpgrading() {
e.Stop(ExitUpgrade)
}
type supervisor interface{ Services() []suture.Service }
func printServiceTree(w io.Writer, sup supervisor, level int) {
printService(w, sup, level)
svcs := sup.Services()
sort.Slice(svcs, func(a, b int) bool {
return fmt.Sprint(svcs[a]) < fmt.Sprint(svcs[b])
})
for _, svc := range svcs {
if sub, ok := svc.(supervisor); ok {
printServiceTree(w, sub, level+1)
} else {
printService(w, svc, level+1)
}
}
}
func printService(w io.Writer, svc interface{}, level int) {
type errorer interface{ Error() error }
t := "-"
if _, ok := svc.(supervisor); ok {
t = "+"
}
fmt.Fprintln(w, strings.Repeat(" ", level), t, svc)
if es, ok := svc.(errorer); ok {
if err := es.Error(); err != nil {
fmt.Fprintln(w, strings.Repeat(" ", level), " ->", err)
}
}
}