Make database backups optional.
Periodic database backups are no longer started automatically in database.Open(), and the backup written by database.Close() can now be disabled. Only vspd itself requires backups, they are not useful for test code or future upcoming tools such as vote-validator.
This commit is contained in:
parent
11401c5369
commit
32790984fe
1
.gitignore
vendored
1
.gitignore
vendored
@ -9,7 +9,6 @@ cov.out
|
||||
*mem.out
|
||||
/webapi/test.db
|
||||
/database/test.db
|
||||
/database/test.db-backup
|
||||
|
||||
# Go workspace
|
||||
go.work
|
||||
|
||||
@ -78,14 +78,18 @@ func run() int {
|
||||
defer log.Criticalf("Shutdown complete")
|
||||
|
||||
// Open database.
|
||||
db, err := database.Open(shutdownCtx, &shutdownWg, dbLog, cfg.dbPath, cfg.BackupInterval, maxVoteChangeRecords)
|
||||
db, err := database.Open(cfg.dbPath, dbLog, maxVoteChangeRecords)
|
||||
if err != nil {
|
||||
log.Errorf("Database error: %v", err)
|
||||
requestShutdown()
|
||||
shutdownWg.Wait()
|
||||
return 1
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
writeBackup := true
|
||||
defer db.Close(writeBackup)
|
||||
|
||||
db.WritePeriodicBackups(shutdownCtx, &shutdownWg, cfg.BackupInterval)
|
||||
|
||||
// Create RPC client for local dcrd instance (used for broadcasting and
|
||||
// checking the status of fee transactions).
|
||||
|
||||
@ -175,9 +175,7 @@ func CreateNew(dbFile, feeXPub string, log slog.Logger) error {
|
||||
|
||||
// Open initializes and returns an open database. An error is returned if no
|
||||
// database file is found at the provided path.
|
||||
func Open(shutdownCtx context.Context, shutdownWg *sync.WaitGroup, log slog.Logger, dbFile string,
|
||||
backupInterval time.Duration, maxVoteChangeRecords int) (*VspDatabase, error) {
|
||||
|
||||
func Open(dbFile string, log slog.Logger, maxVoteChangeRecords int) (*VspDatabase, error) {
|
||||
// Error if db file does not exist. This is needed because bolt.Open will
|
||||
// silently create a new empty database if the file does not exist. A new
|
||||
// vspd database should be created with the CreateNew() function.
|
||||
@ -216,7 +214,15 @@ func Open(shutdownCtx context.Context, shutdownWg *sync.WaitGroup, log slog.Logg
|
||||
return nil, fmt.Errorf("upgrade failed: %w", err)
|
||||
}
|
||||
|
||||
// Periodically update the database backup file.
|
||||
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 {
|
||||
@ -224,7 +230,7 @@ func Open(shutdownCtx context.Context, shutdownWg *sync.WaitGroup, log slog.Logg
|
||||
case <-time.After(backupInterval):
|
||||
err := vdb.writeHotBackupFile()
|
||||
if err != nil {
|
||||
log.Errorf("Failed to write database backup: %v", err)
|
||||
vdb.log.Errorf("Failed to write database backup: %v", err)
|
||||
}
|
||||
case <-shutdownCtx.Done():
|
||||
shutdownWg.Done()
|
||||
@ -232,13 +238,11 @@ func Open(shutdownCtx context.Context, shutdownWg *sync.WaitGroup, log slog.Logg
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return vdb, nil
|
||||
}
|
||||
|
||||
// Close will close the database and then make a copy of the database to the
|
||||
// backup location.
|
||||
func (vdb *VspDatabase) Close() {
|
||||
// Close will close the database and, if requested, make a copy of the database
|
||||
// to the backup location.
|
||||
func (vdb *VspDatabase) Close(writeBackup bool) {
|
||||
|
||||
// Make a copy of the db path here because once the db is closed, db.Path
|
||||
// returns empty string.
|
||||
@ -257,6 +261,10 @@ func (vdb *VspDatabase) Close() {
|
||||
|
||||
vdb.log.Debug("Database closed")
|
||||
|
||||
if !writeBackup {
|
||||
return
|
||||
}
|
||||
|
||||
// Ensure the database backup file is up-to-date.
|
||||
backupPath := dbPath + "-backup"
|
||||
tempPath := backupPath + "~"
|
||||
@ -291,7 +299,7 @@ func (vdb *VspDatabase) Close() {
|
||||
return
|
||||
}
|
||||
|
||||
vdb.log.Tracef("Database backup written to %s", backupPath)
|
||||
vdb.log.Debugf("Database backup written to %s", backupPath)
|
||||
}
|
||||
|
||||
// KeyPair retrieves the keypair used to sign API responses from the database.
|
||||
|
||||
@ -5,7 +5,6 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"io"
|
||||
"math/rand"
|
||||
@ -13,7 +12,6 @@ import (
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strconv"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -22,7 +20,6 @@ import (
|
||||
|
||||
const (
|
||||
testDb = "test.db"
|
||||
backupDb = "test.db-backup"
|
||||
feeXPub = "feexpub"
|
||||
maxVoteChangeRecords = 3
|
||||
|
||||
@ -70,7 +67,6 @@ func stdoutLogger() slog.Logger {
|
||||
func TestDatabase(t *testing.T) {
|
||||
// Ensure we are starting with a clean environment.
|
||||
os.Remove(testDb)
|
||||
os.Remove(backupDb)
|
||||
|
||||
// All sub-tests to run.
|
||||
tests := map[string]func(*testing.T){
|
||||
@ -95,14 +91,13 @@ func TestDatabase(t *testing.T) {
|
||||
for testName, test := range tests {
|
||||
|
||||
// Create a new blank database for each sub-test.
|
||||
var err error
|
||||
var wg sync.WaitGroup
|
||||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
err = CreateNew(testDb, feeXPub, log)
|
||||
err := CreateNew(testDb, feeXPub, log)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating test database: %v", err)
|
||||
}
|
||||
db, err = Open(ctx, &wg, log, testDb, time.Hour, maxVoteChangeRecords)
|
||||
|
||||
// Open the newly created database so it is ready to use.
|
||||
db, err = Open(testDb, log, maxVoteChangeRecords)
|
||||
if err != nil {
|
||||
t.Fatalf("error opening test database: %v", err)
|
||||
}
|
||||
@ -110,14 +105,9 @@ func TestDatabase(t *testing.T) {
|
||||
// Run the sub-test.
|
||||
t.Run(testName, test)
|
||||
|
||||
// Request database shutdown and wait for it to complete.
|
||||
cancel()
|
||||
wg.Wait()
|
||||
|
||||
db.Close()
|
||||
|
||||
writeBackup := false
|
||||
db.Close(writeBackup)
|
||||
os.Remove(testDb)
|
||||
os.Remove(backupDb)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@ package webapi
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ed25519"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@ -15,7 +14,6 @@ import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -33,7 +31,6 @@ const (
|
||||
// (base64 encoding).
|
||||
sigCharset = "0123456789ABCDEFGHJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/="
|
||||
testDb = "test.db"
|
||||
backupDb = "test.db-backup"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -72,17 +69,15 @@ func TestMain(m *testing.M) {
|
||||
// Create a database to use.
|
||||
// Ensure we are starting with a clean environment.
|
||||
os.Remove(testDb)
|
||||
os.Remove(backupDb)
|
||||
|
||||
// Create a new blank database for all tests.
|
||||
var err error
|
||||
var wg sync.WaitGroup
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
err = database.CreateNew(testDb, feeXPub, log)
|
||||
err := database.CreateNew(testDb, feeXPub, log)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error creating test database: %w", err))
|
||||
}
|
||||
db, err := database.Open(ctx, &wg, log, testDb, time.Hour, maxVoteChangeRecords)
|
||||
|
||||
// Open the newly created database so it is ready to use.
|
||||
db, err := database.Open(testDb, log, maxVoteChangeRecords)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("error opening test database: %w", err))
|
||||
}
|
||||
@ -97,12 +92,9 @@ func TestMain(m *testing.M) {
|
||||
// Run tests.
|
||||
exitCode := m.Run()
|
||||
|
||||
// Request database shutdown and wait for it to complete.
|
||||
cancel()
|
||||
wg.Wait()
|
||||
db.Close()
|
||||
writeBackup := false
|
||||
db.Close(writeBackup)
|
||||
os.Remove(testDb)
|
||||
os.Remove(backupDb)
|
||||
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user