vspd: Enable findSpentTickets interrupting.

Add a Context parameter to findSpentTickets so it can be canceled when a
shutdown is requested.
This commit is contained in:
jholdstock 2023-09-07 15:45:01 +01:00 committed by Jamie Holdstock
parent b0f79e56f5
commit ad7c587699
2 changed files with 28 additions and 10 deletions

View File

@ -5,6 +5,7 @@
package main package main
import ( import (
"context"
"fmt" "fmt"
"github.com/decred/dcrd/blockchain/stake/v5" "github.com/decred/dcrd/blockchain/stake/v5"
@ -63,7 +64,8 @@ func (s *spentTicket) missed() bool {
// against the block filters of the mainchain blocks between the provided start // against the block filters of the mainchain blocks between the provided start
// block and the current best block. Returns any found spent tickets and the // block and the current best block. Returns any found spent tickets and the
// height of the most recent scanned block. // height of the most recent scanned block.
func (v *vspd) findSpentTickets(toCheck database.TicketList, startHeight int64) ([]spentTicket, int64, error) { func (v *vspd) findSpentTickets(ctx context.Context, toCheck database.TicketList,
startHeight int64) ([]spentTicket, int64, error) {
params := v.cfg.netParams params := v.cfg.netParams
dcrdClient, _, err := v.dcrd.Client() dcrdClient, _, err := v.dcrd.Client()
@ -118,6 +120,11 @@ func (v *vspd) findSpentTickets(toCheck database.TicketList, startHeight int64)
spent := make([]spentTicket, 0) spent := make([]spentTicket, 0)
for iHeight := startHeight; iHeight <= endHeight; iHeight++ { for iHeight := startHeight; iHeight <= endHeight; iHeight++ {
// Exit early if context has been cancelled.
if ctx.Err() != nil {
return nil, 0, context.Canceled
}
iHash, err := dcrdClient.GetBlockHash(iHeight) iHash, err := dcrdClient.GetBlockHash(iHeight)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err

View File

@ -5,6 +5,7 @@
package main package main
import ( import (
"context"
"errors" "errors"
"fmt" "fmt"
"runtime" "runtime"
@ -120,8 +121,13 @@ func (v *vspd) run() int {
// Run database integrity checks to ensure all data in database is present // Run database integrity checks to ensure all data in database is present
// and up-to-date. // and up-to-date.
err := v.checkDatabaseIntegrity() err := v.checkDatabaseIntegrity(ctx)
if err != nil { if err != nil {
// Don't log error if shutdown was requested, just return.
if errors.Is(err, context.Canceled) {
return 0
}
// vspd should still start if this fails, so just log an error. // vspd should still start if this fails, so just log an error.
v.log.Errorf("Database integrity check failed: %v", err) v.log.Errorf("Database integrity check failed: %v", err)
} }
@ -133,7 +139,7 @@ func (v *vspd) run() int {
// Run the block connected handler now to catch up with any blocks mined // Run the block connected handler now to catch up with any blocks mined
// while vspd was shut down. // while vspd was shut down.
v.blockConnected() v.blockConnected(ctx)
// Stop if shutdown requested. // Stop if shutdown requested.
if ctx.Err() != nil { if ctx.Err() != nil {
@ -209,7 +215,7 @@ func (v *vspd) run() int {
// Handle blockconnected notifications from dcrd. // Handle blockconnected notifications from dcrd.
case header := <-v.blockNotifChan: case header := <-v.blockNotifChan:
v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String()) v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String())
v.blockConnected() v.blockConnected(ctx)
// Handle shutdown request. // Handle shutdown request.
case <-ctx.Done(): case <-ctx.Done():
@ -228,13 +234,13 @@ func (v *vspd) run() int {
// checkDatabaseIntegrity starts the process of ensuring that all data expected // checkDatabaseIntegrity starts the process of ensuring that all data expected
// to be in the database is present and up to date. // to be in the database is present and up to date.
func (v *vspd) checkDatabaseIntegrity() error { func (v *vspd) checkDatabaseIntegrity(ctx context.Context) error {
err := v.checkPurchaseHeights() err := v.checkPurchaseHeights()
if err != nil { if err != nil {
return fmt.Errorf("checkPurchaseHeights error: %w", err) return fmt.Errorf("checkPurchaseHeights error: %w", err)
} }
err = v.checkRevoked() err = v.checkRevoked(ctx)
if err != nil { if err != nil {
return fmt.Errorf("checkRevoked error: %w", err) return fmt.Errorf("checkRevoked error: %w", err)
} }
@ -289,7 +295,7 @@ func (v *vspd) checkPurchaseHeights() error {
// checkRevoked ensures that any tickets in the database with outcome set to // checkRevoked ensures that any tickets in the database with outcome set to
// revoked are updated to either expired or missed. // revoked are updated to either expired or missed.
func (v *vspd) checkRevoked() error { func (v *vspd) checkRevoked(ctx context.Context) error {
revoked, err := v.db.GetRevokedTickets() revoked, err := v.db.GetRevokedTickets()
if err != nil { if err != nil {
return fmt.Errorf("db.GetRevoked error: %w", err) return fmt.Errorf("db.GetRevoked error: %w", err)
@ -307,7 +313,7 @@ func (v *vspd) checkRevoked() error {
// earliest height one of them matured. // earliest height one of them matured.
startHeight := revoked.EarliestPurchaseHeight() + int64(v.cfg.netParams.TicketMaturity) startHeight := revoked.EarliestPurchaseHeight() + int64(v.cfg.netParams.TicketMaturity)
spent, _, err := v.findSpentTickets(revoked, startHeight) spent, _, err := v.findSpentTickets(ctx, revoked, startHeight)
if err != nil { if err != nil {
return fmt.Errorf("findSpentTickets error: %w", err) return fmt.Errorf("findSpentTickets error: %w", err)
} }
@ -345,7 +351,7 @@ func (v *vspd) checkRevoked() error {
// blockConnected is called once when vspd starts up, and once each time a // blockConnected is called once when vspd starts up, and once each time a
// blockconnected notification is received from dcrd. // blockconnected notification is received from dcrd.
func (v *vspd) blockConnected() { func (v *vspd) blockConnected(ctx context.Context) {
const funcName = "blockConnected" const funcName = "blockConnected"
dcrdClient, _, err := v.dcrd.Client() dcrdClient, _, err := v.dcrd.Client()
@ -564,8 +570,13 @@ func (v *vspd) blockConnected() {
startHeight = v.lastScannedBlock startHeight = v.lastScannedBlock
} }
spent, endHeight, err := v.findSpentTickets(votableTickets, startHeight) spent, endHeight, err := v.findSpentTickets(ctx, votableTickets, startHeight)
if err != nil { if err != nil {
// Don't log error if shutdown was requested, just return.
if errors.Is(err, context.Canceled) {
return
}
v.log.Errorf("%s: findSpentTickets error: %v", funcName, err) v.log.Errorf("%s: findSpentTickets error: %v", funcName, err)
return return
} }