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
import (
"context"
"fmt"
"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
// block and the current best block. Returns any found spent tickets and the
// 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
dcrdClient, _, err := v.dcrd.Client()
@ -118,6 +120,11 @@ func (v *vspd) findSpentTickets(toCheck database.TicketList, startHeight int64)
spent := make([]spentTicket, 0)
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)
if err != nil {
return nil, 0, err

View File

@ -5,6 +5,7 @@
package main
import (
"context"
"errors"
"fmt"
"runtime"
@ -120,8 +121,13 @@ func (v *vspd) run() int {
// Run database integrity checks to ensure all data in database is present
// and up-to-date.
err := v.checkDatabaseIntegrity()
err := v.checkDatabaseIntegrity(ctx)
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.
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
// while vspd was shut down.
v.blockConnected()
v.blockConnected(ctx)
// Stop if shutdown requested.
if ctx.Err() != nil {
@ -209,7 +215,7 @@ func (v *vspd) run() int {
// Handle blockconnected notifications from dcrd.
case header := <-v.blockNotifChan:
v.log.Debugf("Block notification %d (%s)", header.Height, header.BlockHash().String())
v.blockConnected()
v.blockConnected(ctx)
// Handle shutdown request.
case <-ctx.Done():
@ -228,13 +234,13 @@ func (v *vspd) run() int {
// 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 {
func (v *vspd) checkDatabaseIntegrity(ctx context.Context) error {
err := v.checkPurchaseHeights()
if err != nil {
return fmt.Errorf("checkPurchaseHeights error: %w", err)
}
err = v.checkRevoked()
err = v.checkRevoked(ctx)
if err != nil {
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
// 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()
if err != nil {
return fmt.Errorf("db.GetRevoked error: %w", err)
@ -307,7 +313,7 @@ func (v *vspd) checkRevoked() error {
// earliest height one of them matured.
startHeight := revoked.EarliestPurchaseHeight() + int64(v.cfg.netParams.TicketMaturity)
spent, _, err := v.findSpentTickets(revoked, startHeight)
spent, _, err := v.findSpentTickets(ctx, revoked, startHeight)
if err != nil {
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 notification is received from dcrd.
func (v *vspd) blockConnected() {
func (v *vspd) blockConnected(ctx context.Context) {
const funcName = "blockConnected"
dcrdClient, _, err := v.dcrd.Client()
@ -564,8 +570,13 @@ func (v *vspd) blockConnected() {
startHeight = v.lastScannedBlock
}
spent, endHeight, err := v.findSpentTickets(votableTickets, startHeight)
spent, endHeight, err := v.findSpentTickets(ctx, votableTickets, startHeight)
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)
return
}