From ec7a8ca61aa294afc7aeb1a2f0bc05221375394c Mon Sep 17 00:00:00 2001 From: surtur Date: Tue, 22 Aug 2023 20:56:32 +0200 Subject: [PATCH] go: run requests scheduler from main * also, actually quit serving on shutdown timeout --- error.go | 9 +++++---- run.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/error.go b/error.go index 8107477..3eadd06 100644 --- a/error.go +++ b/error.go @@ -6,8 +6,9 @@ package main import "errors" var ( - errDBNotConfigured = errors.New("Database connection string or database type were not set") - errUnsupportedDBType = errors.New("DBTYPE can only be one of postgres or sqlite3") - errDBConnFailed = errors.New("Failed to open a connection to the database") - errImportFailed = errors.New("Import of local breach data failed") + errDBNotConfigured = errors.New("Database connection string or database type were not set") + errUnsupportedDBType = errors.New("DBTYPE can only be one of postgres or sqlite3") + errDBConnFailed = errors.New("Failed to open a connection to the database") + errImportFailed = errors.New("Import of local breach data failed") + errHIBPSchedulerFailed = errors.New("HIBP requests scheduler failed") ) diff --git a/run.go b/run.go index 59d6dd8..1a9309a 100644 --- a/run.go +++ b/run.go @@ -11,6 +11,7 @@ import ( "os" "os/signal" "strconv" + "sync" "syscall" "time" @@ -25,6 +26,7 @@ import ( "git.dotya.ml/mirre-mt/pcmt/config" "git.dotya.ml/mirre-mt/pcmt/ent" moddb "git.dotya.ml/mirre-mt/pcmt/modules/db" + "git.dotya.ml/mirre-mt/pcmt/modules/hibp" "git.dotya.ml/mirre-mt/pcmt/modules/localbreach" "git.dotya.ml/mirre-mt/pcmt/slogging" ) @@ -248,9 +250,9 @@ func run() error { //nolint:gocognit // channel used to check whether the app had troubles starting up. started := make(chan error, 1) - defer close(started) + go func() { + defer close(started) - go func(ok chan error) { p := setting.Port() h := setting.Host() @@ -259,38 +261,60 @@ func run() error { //nolint:gocognit if err := e.Start(address); err != nil && err != http.ErrServerClosed { log.Error("troubles running the server, bailing...", "error", err) - ok <- err + started <- err return } - ok <- nil - }(started) + started <- nil + }() quit := make(chan os.Signal, 1) + schedQuit := make(chan os.Signal, 1) + errCh := make(chan error, 1) + wg := &sync.WaitGroup{} - signal.Notify(quit, os.Interrupt) - signal.Notify(quit, syscall.SIGTERM) - signal.Notify(quit, syscall.SIGHUP) + handleSigs(schedQuit, quit) + + go func() { + wg.Add(1) // nolint:staticcheck + go hibp.RunReqScheduler(schedQuit, errCh, wg) // nolint:wsl + }() // non-blocking channel receive. select { + // monitor the server start-up chan. case err := <-started: if err != nil { return err } + case err := <-errCh: + defer func() { + signal.Stop(quit) + + close(quit) + close(errCh) + }() + + if err != nil { + return errHIBPSchedulerFailed + } + case <-quit: + // after the timeout the server forcefully quits. shutdownTimeout := 10 * time.Second + log.Infof("Interrupt received, gracefully shutting down the server (timeout %s)", shutdownTimeout) + ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) defer func() { - log.Infof("Interrupt received, gracefully shutting down the server (timeout %s)", shutdownTimeout) cancel() signal.Stop(quit) close(quit) + close(errCh) log.Info("Bye!") }() @@ -299,11 +323,29 @@ func run() error { //nolint:gocognit log.Error("There was an error shutting the server down") return err } + + select { + case <-ctx.Done(): + log.Error("Failed to stop the server in time, yolo") + return ctx.Err() + + default: + wg.Wait() + } } return nil } +// handleSigs configures given chans to be notified on os signals. +func handleSigs(chans ...chan os.Signal) { + sigs := []os.Signal{os.Interrupt, syscall.SIGHUP, syscall.SIGTERM} + + for _, ch := range chans { + signal.Notify(ch, sigs...) + } +} + func printHeader() { slug := fmt.Sprintf(slug, version)