diff --git a/cmd/vspd/vspd.go b/cmd/vspd/vspd.go index e638742..f362175 100644 --- a/cmd/vspd/vspd.go +++ b/cmd/vspd/vspd.go @@ -118,11 +118,6 @@ func (v *vspd) run() int { // through an interrupt signal. shutdownCtx := shutdownListener(v.log) - // WaitGroup for services to signal when they have shutdown cleanly. - var shutdownWg sync.WaitGroup - - v.db.WritePeriodicBackups(shutdownCtx, &shutdownWg, v.cfg.BackupInterval) - // Run database integrity checks to ensure all data in database is present // and up-to-date. err := v.checkDatabaseIntegrity() @@ -139,19 +134,8 @@ func (v *vspd) run() int { // date. v.checkWalletConsistency() - // Run voting wallet consistency check periodically. - shutdownWg.Add(1) - go func() { - for { - select { - case <-shutdownCtx.Done(): - shutdownWg.Done() - return - case <-time.After(consistencyInterval): - v.checkWalletConsistency() - } - } - }() + // WaitGroup for services to signal when they have shutdown cleanly. + var shutdownWg sync.WaitGroup // Create and start webapi server. apiCfg := webapi.Config{ @@ -176,36 +160,46 @@ func (v *vspd) run() int { return 1 } - // Start handling blockConnected notifications from dcrd. + // Start all background tasks and notification handlers. shutdownWg.Add(1) go func() { - for { - select { - case <-shutdownCtx.Done(): - shutdownWg.Done() - return - case header := <-v.blockNotifChan: - v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String()) - v.blockConnected() - } - } - }() + backupTicker := time.NewTicker(v.cfg.BackupInterval) + defer backupTicker.Stop() + consistencyTicker := time.NewTicker(consistencyInterval) + defer consistencyTicker.Stop() + dcrdTicker := time.NewTicker(dcrdInterval) + defer dcrdTicker.Stop() - // Loop forever attempting ensuring a dcrd connection is available, so - // notifications are received. - shutdownWg.Add(1) - go func() { for { select { - case <-shutdownCtx.Done(): - shutdownWg.Done() - return - case <-time.After(dcrdInterval): - // Ensure dcrd client is still connected. + + // Periodically write a database backup file. + case <-backupTicker.C: + err := v.db.WriteHotBackupFile() + if err != nil { + v.log.Errorf("Failed to write database backup: %v", err) + } + + // Run voting wallet consistency check periodically. + case <-consistencyTicker.C: + v.checkWalletConsistency() + + // Ensure dcrd client is connected so notifications are received. + case <-dcrdTicker.C: _, _, err := v.dcrd.Client() if err != nil { v.log.Errorf("dcrd connect error: %v", err) } + + // Handle blockconnected notifications from dcrd. + case header := <-v.blockNotifChan: + v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String()) + v.blockConnected() + + // Handle shutdown request. + case <-shutdownCtx.Done(): + shutdownWg.Done() + return } } }() diff --git a/database/database.go b/database/database.go index d12e15e..c9ac930 100644 --- a/database/database.go +++ b/database/database.go @@ -5,7 +5,6 @@ package database import ( - "context" "crypto/ed25519" "crypto/rand" "fmt" @@ -61,9 +60,9 @@ const ( // backupMtx should be held when writing to the database backup file. var backupMtx sync.Mutex -// writeHotBackupFile writes a backup of the database file while the database +// WriteHotBackupFile writes a backup of the database file while the database // is still open. -func (vdb *VspDatabase) writeHotBackupFile() error { +func (vdb *VspDatabase) WriteHotBackupFile() error { backupMtx.Lock() defer backupMtx.Unlock() @@ -216,29 +215,6 @@ func Open(dbFile string, log slog.Logger, maxVoteChangeRecords int) (*VspDatabas return vdb, nil } -// WritePeriodicBackups starts a goroutine to periodically write a database backup file. -// It can be stopped by cancelling the provided context, and uses the provided -// WaitGroup to signal that it has finished. -func (vdb *VspDatabase) WritePeriodicBackups(shutdownCtx context.Context, shutdownWg *sync.WaitGroup, - backupInterval time.Duration) { - - shutdownWg.Add(1) - go func() { - for { - select { - case <-time.After(backupInterval): - err := vdb.writeHotBackupFile() - if err != nil { - vdb.log.Errorf("Failed to write database backup: %v", err) - } - case <-shutdownCtx.Done(): - shutdownWg.Done() - return - } - } - }() -} - // Close will close the database and, if requested, make a copy of the database // to the backup location. func (vdb *VspDatabase) Close(writeBackup bool) {