vspd: Consolidate background task timers.
Using a single select loop for background tasks removes a lot of duplicated boilerplate code and helps to simplify shutdown logic. This does reduce the amount of things which can run in parallel, but that isn't of concern for vspd. The web server still runs in its own goroutine so its responsiveness won't be affected.
This commit is contained in:
parent
cfc34a3adc
commit
8df00752c0
@ -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
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user