chore(db): add ability to wait for programmatically started database maintenance, query last maintenance time (#10565)

Also adds a method to query the last database maintenance time.

Signed-off-by: Tommy van der Vorst <tommy@pixelspark.nl>
Co-authored-by: Jakob Borg <jakob@kastelo.net>
This commit is contained in:
Tommy van der Vorst
2026-02-11 09:28:11 +00:00
committed by GitHub
co-authored by Jakob Borg
parent 0b5a08c99a
commit 5cf9168dc2
3 changed files with 33 additions and 9 deletions
+6 -1
View File
@@ -19,7 +19,12 @@ type DBService interface {
suture.Service
// Starts maintenance asynchronously, if not already running
StartMaintenance()
// Returns a channel that will receive the result when the requested maintenance finishes
StartMaintenance() <-chan error
// Returns the last time database maintenance completed
// This will return time zero when database maintenance has never completed successfully.
LastMaintenanceTime() time.Time
}
type DB interface {
+19 -6
View File
@@ -39,7 +39,7 @@ type Service struct {
sdb *DB
maintenanceInterval time.Duration
internalMeta *db.Typed
start chan struct{}
start chan chan error
}
func (s *Service) String() string {
@@ -51,15 +51,17 @@ func newService(sdb *DB, maintenanceInterval time.Duration) *Service {
sdb: sdb,
maintenanceInterval: maintenanceInterval,
internalMeta: db.NewTyped(sdb, internalMetaPrefix),
start: make(chan struct{}),
start: make(chan chan error),
}
}
func (s *Service) StartMaintenance() {
func (s *Service) StartMaintenance() <-chan error {
finishChan := make(chan error, 1)
select {
case s.start <- struct{}{}:
case s.start <- finishChan:
default:
}
return finishChan
}
func (s *Service) Serve(ctx context.Context) error {
@@ -80,14 +82,20 @@ func (s *Service) Serve(ctx context.Context) error {
}
for {
var finishChan chan error
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
case <-s.start:
case finishChan = <-s.start:
}
if err := s.periodic(ctx); err != nil {
err := s.periodic(ctx)
if finishChan != nil {
finishChan <- err
}
if err != nil {
return wrap(err)
}
@@ -100,6 +108,11 @@ func (s *Service) Serve(ctx context.Context) error {
}
}
func (s *Service) LastMaintenanceTime() time.Time {
lastMaint, _, _ := s.internalMeta.Time(lastMaintKey)
return lastMaint
}
func (s *Service) periodic(ctx context.Context) error {
t0 := time.Now()
slog.DebugContext(ctx, "Periodic start")
+8 -2
View File
@@ -116,8 +116,14 @@ func (a *App) Start() error {
}
// StartMaintenance asynchronously triggers database maintenance to start.
func (a *App) StartMaintenance() {
a.dbService.StartMaintenance()
func (a *App) StartMaintenance() <-chan error {
return a.dbService.StartMaintenance()
}
// LastMaintenanceTime returns the last time database maintenance completed successfully
// This will return time zero when database maintenance has never completed successfully.
func (a *App) LastMaintenanceTime() time.Time {
return a.dbService.LastMaintenanceTime()
}
func (a *App) startup() error {