Manager: perform database integrity check every hour
Perform a database integrity check every hour. This check was already performed at startup, in the main goroutine.
This commit is contained in:
parent
5eb57427fc
commit
4121c899c3
@ -139,12 +139,6 @@ func runFlamencoManager() bool {
|
|||||||
persist := openDB(*configService)
|
persist := openDB(*configService)
|
||||||
defer persist.Close()
|
defer persist.Close()
|
||||||
|
|
||||||
// Disabled for now. `VACUUM` locks the database, which means that other
|
|
||||||
// queries can fail with a "database is locked (5) (SQLITE_BUSY)" error. This
|
|
||||||
// situation should be handled gracefully before reinstating the vacuum loop.
|
|
||||||
//
|
|
||||||
// go persist.PeriodicMaintenanceLoop(mainCtx)
|
|
||||||
|
|
||||||
timeService := clock.New()
|
timeService := clock.New()
|
||||||
compiler, err := job_compilers.Load(timeService)
|
compiler, err := job_compilers.Load(timeService)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -196,6 +190,14 @@ func runFlamencoManager() bool {
|
|||||||
lastRender.Run(mainCtx)
|
lastRender.Run(mainCtx)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Run a periodic integrity check on the database.
|
||||||
|
// When that check fails, the entire application should shut down.
|
||||||
|
wg.Add(1)
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
persist.PeriodicIntegrityCheck(mainCtx, mainCtxCancel)
|
||||||
|
}()
|
||||||
|
|
||||||
// Start the web server.
|
// Start the web server.
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -15,8 +15,6 @@ import (
|
|||||||
"github.com/glebarez/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
const checkPeriod = 1 * time.Hour
|
|
||||||
|
|
||||||
// DB provides the database interface.
|
// DB provides the database interface.
|
||||||
type DB struct {
|
type DB struct {
|
||||||
gormDB *gorm.DB
|
gormDB *gorm.DB
|
||||||
|
@ -12,7 +12,10 @@ import (
|
|||||||
|
|
||||||
var ErrIntegrity = errors.New("database integrity check failed")
|
var ErrIntegrity = errors.New("database integrity check failed")
|
||||||
|
|
||||||
const integrityCheckTimeout = 2 * time.Second
|
const (
|
||||||
|
integrityCheckTimeout = 2 * time.Second
|
||||||
|
integrityCheckPeriod = 1 * time.Hour
|
||||||
|
)
|
||||||
|
|
||||||
type PragmaIntegrityCheckResult struct {
|
type PragmaIntegrityCheckResult struct {
|
||||||
Description string `gorm:"column:integrity_check"`
|
Description string `gorm:"column:integrity_check"`
|
||||||
@ -25,6 +28,27 @@ type PragmaForeignKeyCheckResult struct {
|
|||||||
FKID int `gorm:"column:fkid"`
|
FKID int `gorm:"column:fkid"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PeriodicIntegrityCheck periodically checks the database integrity.
|
||||||
|
// This function only returns when the context is done.
|
||||||
|
func (db *DB) PeriodicIntegrityCheck(ctx context.Context, onErrorCallback func()) {
|
||||||
|
log.Debug().Msg("database: periodic integrity check loop starting")
|
||||||
|
defer log.Debug().Msg("database: periodic integrity check loop stopping")
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-time.After(integrityCheckPeriod):
|
||||||
|
}
|
||||||
|
|
||||||
|
ok := db.performIntegrityCheck(ctx)
|
||||||
|
if !ok {
|
||||||
|
log.Error().Msg("database: periodic integrity check failed")
|
||||||
|
onErrorCallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// performIntegrityCheck uses a few 'pragma' SQL statements to do some integrity checking.
|
// performIntegrityCheck uses a few 'pragma' SQL statements to do some integrity checking.
|
||||||
// Returns true on OK, false if there was an issue. Issues are always logged.
|
// Returns true on OK, false if there was an issue. Issues are always logged.
|
||||||
func (db *DB) performIntegrityCheck(ctx context.Context) (ok bool) {
|
func (db *DB) performIntegrityCheck(ctx context.Context) (ok bool) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user