app: wire checker retention janitor and user gate
Construct the retention janitor and the user gate alongside the checker scheduler. Three new options drive their behaviour: --checker-retention-days (default 365) --checker-janitor-interval (default 6h) --checker-inactivity-pause-days (default 90) The janitor starts immediately on App.Start and is shut down on App.Stop. The user gate is installed on the scheduler with the same storage-backed user resolver, so paused users and users that haven't logged in for the configured horizon stop being checked until they come back.
This commit is contained in:
parent
64dbf6287e
commit
5cbe3f580f
3 changed files with 43 additions and 0 deletions
|
|
@ -76,6 +76,7 @@ type Usecases struct {
|
|||
checkerPlanUC *checkerUC.CheckPlanUsecase
|
||||
checkerStatusUC *checkerUC.CheckStatusUsecase
|
||||
checkerScheduler *checkerUC.Scheduler
|
||||
checkerJanitor *checkerUC.Janitor
|
||||
}
|
||||
|
||||
type App struct {
|
||||
|
|
@ -273,6 +274,21 @@ func (app *App) initUsecases() {
|
|||
)
|
||||
app.usecases.checkerScheduler = checkerUC.NewScheduler(app.usecases.checkerEngine, app.cfg.CheckerMaxConcurrency, app.store, app.store, app.store, app.store)
|
||||
|
||||
// Install the user-level gate so paused or long-inactive users do not
|
||||
// get checked. The same user resolver is reused by the janitor for
|
||||
// per-user retention overrides.
|
||||
gater := checkerUC.NewUserGater(app.store, app.cfg.CheckerInactivityPauseDays)
|
||||
app.usecases.checkerScheduler.SetGate(gater.Allow)
|
||||
|
||||
// Retention janitor.
|
||||
app.usecases.checkerJanitor = checkerUC.NewJanitor(
|
||||
app.store,
|
||||
app.store,
|
||||
app.store,
|
||||
checkerUC.DefaultRetentionPolicy(app.cfg.CheckerRetentionDays),
|
||||
app.cfg.CheckerJanitorInterval,
|
||||
)
|
||||
|
||||
// Wire scheduler notifications for incremental queue updates.
|
||||
domainService.SetSchedulerNotifier(app.usecases.checkerScheduler)
|
||||
app.usecases.orchestrator.SetSchedulerNotifier(app.usecases.checkerScheduler)
|
||||
|
|
@ -348,6 +364,10 @@ func (app *App) Start() {
|
|||
app.usecases.checkerScheduler.Start(context.Background())
|
||||
}
|
||||
|
||||
if app.usecases.checkerJanitor != nil {
|
||||
app.usecases.checkerJanitor.Start(context.Background())
|
||||
}
|
||||
|
||||
log.Printf("Public interface listening on %s\n", app.cfg.Bind)
|
||||
if err := app.srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
log.Fatalf("listen: %s\n", err)
|
||||
|
|
@ -365,6 +385,10 @@ func (app *App) Stop() {
|
|||
app.usecases.checkerScheduler.Stop()
|
||||
}
|
||||
|
||||
if app.usecases.checkerJanitor != nil {
|
||||
app.usecases.checkerJanitor.Stop()
|
||||
}
|
||||
|
||||
// Close storage
|
||||
if app.store != nil {
|
||||
app.store.Close()
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"git.happydns.org/happyDomain/internal/storage"
|
||||
"git.happydns.org/happyDomain/model"
|
||||
|
|
@ -47,6 +48,9 @@ func declareFlags(o *happydns.Options) {
|
|||
flag.Var(&URL{&o.ExternalAuth}, "external-auth", "Base URL to use for login and registration (use embedded forms if left empty)")
|
||||
flag.BoolVar(&o.OptOutInsights, "opt-out-insights", false, "Disable the anonymous usage statistics report. If you care about this project and don't participate in discussions, don't opt-out.")
|
||||
flag.IntVar(&o.CheckerMaxConcurrency, "checker-max-concurrency", runtime.NumCPU(), "Maximum number of checker jobs that can run simultaneously")
|
||||
flag.IntVar(&o.CheckerRetentionDays, "checker-retention-days", 365, "System-wide default retention horizon for check execution history (overridable per user)")
|
||||
flag.DurationVar(&o.CheckerJanitorInterval, "checker-janitor-interval", 6*time.Hour, "How often the checker retention janitor runs")
|
||||
flag.IntVar(&o.CheckerInactivityPauseDays, "checker-inactivity-pause-days", 90, "Pause checks for users that haven't logged in for this many days (0 disables, overridable per user)")
|
||||
|
||||
flag.Var(&URL{&o.ListmonkURL}, "newsletter-server-url", "Base URL of the listmonk newsletter server")
|
||||
flag.IntVar(&o.ListmonkID, "newsletter-id", 1, "Listmonk identifier of the list receiving the new user")
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"net/mail"
|
||||
"net/url"
|
||||
"path"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Options stores the configuration of the software.
|
||||
|
|
@ -97,6 +98,20 @@ type Options struct {
|
|||
// run simultaneously. Defaults to runtime.NumCPU().
|
||||
CheckerMaxConcurrency int
|
||||
|
||||
// CheckerRetentionDays is the system-wide default for how many days of
|
||||
// check execution history are kept. Per-user UserQuota.RetentionDays
|
||||
// overrides this value.
|
||||
CheckerRetentionDays int
|
||||
|
||||
// CheckerJanitorInterval is how often the retention janitor runs.
|
||||
CheckerJanitorInterval time.Duration
|
||||
|
||||
// CheckerInactivityPauseDays is the system-wide default number of days
|
||||
// without login after which the scheduler stops running checks for a
|
||||
// user. 0 disables inactivity pausing globally; per-user UserQuota
|
||||
// overrides this value.
|
||||
CheckerInactivityPauseDays int
|
||||
|
||||
// CaptchaProvider selects the captcha provider ("hcaptcha", "recaptchav2", "turnstile", or "").
|
||||
CaptchaProvider string
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue