0
Fork 0
mirror of https://github.com/project-zot/zot.git synced 2025-01-06 22:40:28 -05:00
zot/pkg/extensions/search/cve/update.go
peusebiu 6222dae1f0
feat(scheduler): gracefully shutdown (#1951)
wait for workers to finish before exiting

should fix tests reporting they couldn't remove rootDir because it's being
written by tasks

Signed-off-by: Petu Eusebiu <peusebiu@cisco.com>
2023-11-24 00:40:10 -08:00

120 lines
2.2 KiB
Go

package cveinfo
import (
"context"
"sync"
"time"
"zotregistry.io/zot/pkg/log"
"zotregistry.io/zot/pkg/scheduler"
)
type state int
const (
pending state = iota
running
done
)
func NewDBUpdateTaskGenerator(
interval time.Duration,
scanner Scanner,
log log.Logger,
) scheduler.TaskGenerator {
generator := &DBUpdateTaskGenerator{
interval,
scanner,
log,
pending,
0,
time.Now(),
&sync.Mutex{},
}
return generator
}
type DBUpdateTaskGenerator struct {
interval time.Duration
scanner Scanner
log log.Logger
status state
waitTime time.Duration
lastTaskTime time.Time
lock *sync.Mutex
}
func (gen *DBUpdateTaskGenerator) Next() (scheduler.Task, error) {
var newTask scheduler.Task
gen.lock.Lock()
if gen.status == pending && time.Since(gen.lastTaskTime) >= gen.waitTime {
newTask = newDBUpdadeTask(gen.interval, gen.scanner, gen, gen.log)
gen.status = running
}
gen.lock.Unlock()
return newTask, nil
}
func (gen *DBUpdateTaskGenerator) IsDone() bool {
gen.lock.Lock()
status := gen.status
gen.lock.Unlock()
return status == done
}
func (gen *DBUpdateTaskGenerator) IsReady() bool {
return true
}
func (gen *DBUpdateTaskGenerator) Reset() {
gen.lock.Lock()
gen.status = pending
gen.waitTime = 0
gen.lock.Unlock()
}
type dbUpdateTask struct {
interval time.Duration
scanner Scanner
generator *DBUpdateTaskGenerator
log log.Logger
}
func newDBUpdadeTask(interval time.Duration, scanner Scanner,
generator *DBUpdateTaskGenerator, log log.Logger,
) *dbUpdateTask {
return &dbUpdateTask{interval, scanner, generator, log}
}
func (dbt *dbUpdateTask) DoWork(ctx context.Context) error {
dbt.log.Info().Msg("updating the CVE database")
err := dbt.scanner.UpdateDB(ctx)
if err != nil {
dbt.generator.lock.Lock()
dbt.generator.status = pending
if dbt.generator.waitTime == 0 {
dbt.generator.waitTime = time.Second
}
dbt.generator.waitTime *= 2
dbt.generator.lastTaskTime = time.Now()
dbt.generator.lock.Unlock()
return err
}
dbt.generator.lock.Lock()
dbt.generator.lastTaskTime = time.Now()
dbt.generator.status = done
dbt.generator.lock.Unlock()
dbt.log.Info().Str("DB update completed, next update scheduled after", dbt.interval.String()).Msg("")
return nil
}