diff --git a/backend/app/api/app.go b/backend/app/api/app.go index 73d7809..5d285d3 100644 --- a/backend/app/api/app.go +++ b/backend/app/api/app.go @@ -1,22 +1,18 @@ package main import ( - "time" - "github.com/hay-kot/homebox/backend/internal/core/services" "github.com/hay-kot/homebox/backend/internal/core/services/reporting/eventbus" "github.com/hay-kot/homebox/backend/internal/data/ent" "github.com/hay-kot/homebox/backend/internal/data/repo" "github.com/hay-kot/homebox/backend/internal/sys/config" "github.com/hay-kot/homebox/backend/pkgs/mailer" - "github.com/hay-kot/httpkit/server" ) type app struct { conf *config.Config mailer mailer.Mailer db *ent.Client - server *server.Server repos *repo.AllRepos services *services.AllServices bus *eventbus.EventBus @@ -37,13 +33,3 @@ func new(conf *config.Config) *app { return s } - -func (a *app) startBgTask(t time.Duration, fn func()) { - timer := time.NewTimer(t) - - for { - timer.Reset(t) - a.server.Background(fn) - <-timer.C - } -} diff --git a/backend/app/api/bgrunner.go b/backend/app/api/bgrunner.go new file mode 100644 index 0000000..a05d496 --- /dev/null +++ b/backend/app/api/bgrunner.go @@ -0,0 +1,37 @@ +package main + +import ( + "context" + "time" +) + +type BackgroundTask struct { + name string + Interval time.Duration + Fn func(context.Context) +} + +func (bg *BackgroundTask) Name() string { + return bg.name +} + +func NewTask(name string, interval time.Duration, fn func(context.Context)) *BackgroundTask { + return &BackgroundTask{ + Interval: interval, + Fn: fn, + } +} + +func (tsk *BackgroundTask) Start(ctx context.Context) error { + timer := time.NewTimer(tsk.Interval) + + for { + select { + case <-ctx.Done(): + return nil + case <-timer.C: + timer.Reset(tsk.Interval) + tsk.Fn(ctx) + } + } +} diff --git a/backend/app/api/main.go b/backend/app/api/main.go index 8a9f03e..0a352e9 100644 --- a/backend/app/api/main.go +++ b/backend/app/api/main.go @@ -178,7 +178,7 @@ func run(cfg *config.Config) error { middleware.StripSlashes, ) - chain := errchain.New(mid.Errors(app.server, logger)) + chain := errchain.New(mid.Errors(logger)) app.mountRoutes(router, chain, app.repos) @@ -186,8 +186,8 @@ func run(cfg *config.Config) error { runner.AddFunc("server", func(ctx context.Context) error { httpserver := http.Server{ - Addr: fmt.Sprintf("%s:%s", app.server.Host, app.server.Port), - Handler: router, + Addr: fmt.Sprintf("%s:%s", cfg.Web.Host, cfg.Web.Port), + Handler: router, ReadTimeout: cfg.Web.ReadTimeout, WriteTimeout: cfg.Web.WriteTimeout, IdleTimeout: cfg.Web.IdleTimeout, @@ -195,36 +195,37 @@ func run(cfg *config.Config) error { go func() { <-ctx.Done() - httpserver.Shutdown(context.Background()) + _ = httpserver.Shutdown(context.Background()) }() + log.Info().Msgf("Server is running on %s:%s", cfg.Web.Host, cfg.Web.Port) return httpserver.ListenAndServe() }) - log.Info().Msgf("Starting HTTP Server on %s:%s", app.server.Host, app.server.Port) - // ========================================================================= // Start Reoccurring Tasks runner.AddFunc("eventbus", app.bus.Run) - go app.startBgTask(time.Duration(24)*time.Hour, func() { - _, err := app.repos.AuthTokens.PurgeExpiredTokens(context.Background()) + runner.AddPlugin(NewTask("purge-tokens", time.Duration(24)*time.Hour, func(ctx context.Context) { + _, err := app.repos.AuthTokens.PurgeExpiredTokens(ctx) if err != nil { log.Error(). Err(err). Msg("failed to purge expired tokens") } - }) - go app.startBgTask(time.Duration(24)*time.Hour, func() { - _, err := app.repos.Groups.InvitationPurge(context.Background()) + })) + + runner.AddPlugin(NewTask("purge-invitations", time.Duration(24)*time.Hour, func(ctx context.Context) { + _, err := app.repos.Groups.InvitationPurge(ctx) if err != nil { log.Error(). Err(err). Msg("failed to purge expired invitations") } - }) - go app.startBgTask(time.Duration(1)*time.Hour, func() { + })) + + runner.AddPlugin(NewTask("send-notifications", time.Duration(1)*time.Hour, func(ctx context.Context) { now := time.Now() if now.Hour() == 8 { @@ -236,7 +237,7 @@ func run(cfg *config.Config) error { Msg("failed to send notifiers") } } - }) + })) // TODO: Remove through external API that does setup if cfg.Demo { @@ -256,9 +257,10 @@ func run(cfg *config.Config) error { go func() { <-ctx.Done() - debugserver.Shutdown(context.Background()) + _ = debugserver.Shutdown(context.Background()) }() + log.Info().Msgf("Debug server is running on %s:%s", cfg.Web.Host, cfg.Debug.Port) return debugserver.ListenAndServe() }) } diff --git a/backend/internal/data/repo/main_test.go b/backend/internal/data/repo/main_test.go index ad5fcb9..47e5ec0 100644 --- a/backend/internal/data/repo/main_test.go +++ b/backend/internal/data/repo/main_test.go @@ -45,7 +45,9 @@ func TestMain(m *testing.M) { log.Fatalf("failed opening connection to sqlite: %v", err) } - go tbus.Run() + go func() { + _ = tbus.Run(context.Background()) + }() err = client.Schema.Create(context.Background()) if err != nil { diff --git a/backend/internal/web/mid/errors.go b/backend/internal/web/mid/errors.go index c619477..c8b04d6 100644 --- a/backend/internal/web/mid/errors.go +++ b/backend/internal/web/mid/errors.go @@ -16,7 +16,7 @@ type ErrorResponse struct { Fields map[string]string `json:"fields,omitempty"` } -func Errors(svr *server.Server, log zerolog.Logger) errchain.ErrorHandler { +func Errors(log zerolog.Logger) errchain.ErrorHandler { return func(h errchain.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { err := h.ServeHTTP(w, r) @@ -71,14 +71,6 @@ func Errors(svr *server.Server, log zerolog.Logger) errchain.ErrorHandler { if err := server.JSON(w, code, resp); err != nil { log.Err(err).Msg("failed to write response") } - - // If Showdown error, return error - if server.IsShutdownError(err) { - err := svr.Shutdown(err.Error()) - if err != nil { - log.Err(err).Msg("failed to shutdown server") - } - } } }) }