Skip to content

Commit

Permalink
multi: Hoist database integrity checks up to vspd.
Browse files Browse the repository at this point in the history
Moving the existing integrity checks up into vspd removes the
depdendancy on rpc clients from the database client, and also creates a
natural home for future integrity checks to be added.
  • Loading branch information
jholdstock committed Aug 23, 2023
1 parent b1fbced commit bac0dce
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 53 deletions.
63 changes: 60 additions & 3 deletions cmd/vspd/vspd.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,12 @@ func (v *vspd) run() int {

v.db.WritePeriodicBackups(shutdownCtx, &shutdownWg, v.cfg.BackupInterval)

// Ensure all data in database is present and up-to-date.
err := v.db.CheckIntegrity(v.dcrd)
// Run database integrity checks to ensure all data in database is present
// and up-to-date.
err := v.checkDatabaseIntegrity()
if err != nil {
// vspd should still start if this fails, so just log an error.
v.log.Errorf("Could not check database integrity: %v", err)
v.log.Errorf("Database integrity check failed: %v", err)
}

// Run the block connected handler now to catch up with any blocks mined
Expand Down Expand Up @@ -206,6 +207,62 @@ func (v *vspd) run() int {
return 0
}

// checkDatabaseIntegrity starts the process of ensuring that all data expected
// to be in the database is present and up to date.
func (v *vspd) checkDatabaseIntegrity() error {
err := v.checkPurchaseHeights()
if err != nil {
return err
}

return nil
}

// checkPurchaseHeights ensures a purchase height is recorded for all confirmed
// tickets in the database. This is necessary because of an old bug which, in
// some circumstances, would prevent purchase height from being stored.
func (v *vspd) checkPurchaseHeights() error {
missing, err := v.db.GetMissingPurchaseHeight()
if err != nil {
// Cannot proceed if this fails, return.
return fmt.Errorf("db.GetMissingPurchaseHeight error: %w", err)
}

if len(missing) == 0 {
// Nothing to do, return.
return nil
}

v.log.Warnf("%d tickets are missing purchase heights", len(missing))

dcrdClient, _, err := v.dcrd.Client()
if err != nil {
// Cannot proceed if this fails, return.
return err
}

fixed := 0
for _, ticket := range missing {
tktTx, err := dcrdClient.GetRawTransaction(ticket.Hash)
if err != nil {
// Just log and continue, other tickets might succeed.
v.log.Errorf("Could not get raw tx for ticket %s: %v", ticket.Hash, err)
continue
}
ticket.PurchaseHeight = tktTx.BlockHeight
err = v.db.UpdateTicket(ticket)
if err != nil {
// Just log and continue, other tickets might succeed.
v.log.Errorf("Could not insert purchase height for ticket %s: %v", ticket.Hash, err)
continue
}
fixed++
}

v.log.Infof("Added missing purchase height to %d tickets", fixed)
return nil
}

// blockConnected is called once when vspd starts up, and once each time a
// blockconnected notification is received from dcrd.
func (v *vspd) blockConnected() {
Expand Down
50 changes: 0 additions & 50 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"time"

"github.com/decred/slog"
"github.com/decred/vspd/rpc"
bolt "go.etcd.io/bbolt"
)

Expand Down Expand Up @@ -405,52 +404,3 @@ func (vdb *VspDatabase) BackupDB(w http.ResponseWriter) error {

return err
}

// CheckIntegrity will ensure that all data expected to be in the database is
// present and up to date.
func (vdb *VspDatabase) CheckIntegrity(dcrd rpc.DcrdConnect) error {

// Ensure a purchase height is recorded for all confirmed tickets in the
// database. This is necessary because of an old bug which, in some
// circumstances, would prevent purchase height from being stored.

missing, err := vdb.GetMissingPurchaseHeight()
if err != nil {
// Cannot proceed if this fails, return.
return fmt.Errorf("db.GetMissingPurchaseHeight error: %w", err)
}

if len(missing) == 0 {
// Nothing to do, return.
return nil
}

vdb.log.Warnf("%d tickets are missing purchase heights", len(missing))

dcrdClient, _, err := dcrd.Client()
if err != nil {
// Cannot proceed if this fails, return.
return err
}

fixed := 0
for _, ticket := range missing {
tktTx, err := dcrdClient.GetRawTransaction(ticket.Hash)
if err != nil {
// Just log and continue, other tickets might succeed.
vdb.log.Errorf("Could not get raw tx for ticket %s: %v", ticket.Hash, err)
continue
}
ticket.PurchaseHeight = tktTx.BlockHeight
err = vdb.UpdateTicket(ticket)
if err != nil {
// Just log and continue, other tickets might succeed.
vdb.log.Errorf("Could not insert purchase height for ticket %s: %v", ticket.Hash, err)
continue
}
fixed++
}

vdb.log.Infof("Added missing purchase height to %d tickets", fixed)
return nil
}

0 comments on commit bac0dce

Please sign in to comment.