Update websocket clients with rescan progress.
This change periodically (about every 10 seconds) notifies the connected websocket client of the height of the last processed block as part of the rescan. This enables clients to listen for the notification and keep track of how much progress a rescan has made even without any results being found. If the websocket connection is lost during the rescan, on reconnect, clients may safely start over at the last notified height.
This commit is contained in:
parent
5932cd5385
commit
d702e37141
1 changed files with 33 additions and 8 deletions
|
@ -1675,10 +1675,15 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error)
|
||||||
minBlock := int64(cmd.BeginBlock)
|
minBlock := int64(cmd.BeginBlock)
|
||||||
maxBlock := int64(cmd.EndBlock)
|
maxBlock := int64(cmd.EndBlock)
|
||||||
|
|
||||||
|
// A ticker is created to wait at least 10 seconds before notifying the
|
||||||
|
// websocket client of the current progress completed by the rescan.
|
||||||
|
ticker := time.NewTicker(10 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
// FetchHeightRange may not return a complete list of block shas for
|
// FetchHeightRange may not return a complete list of block shas for
|
||||||
// the given range, so fetch range as many times as necessary.
|
// the given range, so fetch range as many times as necessary.
|
||||||
db := wsc.server.server.db
|
db := wsc.server.server.db
|
||||||
for {
|
for minBlock < maxBlock {
|
||||||
hashList, err := db.FetchHeightRange(minBlock, maxBlock)
|
hashList, err := db.FetchHeightRange(minBlock, maxBlock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rpcsLog.Errorf("Error looking up block range: %v", err)
|
rpcsLog.Errorf("Error looking up block range: %v", err)
|
||||||
|
@ -1699,19 +1704,39 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error)
|
||||||
// client requesting the rescan has disconnected.
|
// client requesting the rescan has disconnected.
|
||||||
select {
|
select {
|
||||||
case <-wsc.quit:
|
case <-wsc.quit:
|
||||||
rpcsLog.Debugf("Stopped rescan at height %v for disconnected client",
|
rpcsLog.Debugf("Stopped rescan at height %v "+
|
||||||
blk.Height())
|
"for disconnected client", blk.Height())
|
||||||
return nil, nil
|
return nil, nil
|
||||||
default:
|
default:
|
||||||
rescanBlock(wsc, &lookups, blk)
|
rescanBlock(wsc, &lookups, blk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Periodically notify the client of the progress
|
||||||
|
// completed. Continue with next block if no progress
|
||||||
|
// notification is needed yet.
|
||||||
|
select {
|
||||||
|
case <-ticker.C: // fallthrough
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
n := btcws.NewRescanProgressNtfn(int32(blk.Height()))
|
||||||
|
mn, err := n.MarshalJSON()
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("Failed to marshal rescan "+
|
||||||
|
"progress notification: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = wsc.QueueNotification(mn); err == ErrClientQuit {
|
||||||
|
// Finished if the client disconnected.
|
||||||
|
rpcsLog.Debugf("Stopped rescan at height %v "+
|
||||||
|
"for disconnected client", blk.Height())
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if maxBlock-minBlock > int64(len(hashList)) {
|
minBlock += int64(len(hashList))
|
||||||
minBlock += int64(len(hashList))
|
|
||||||
} else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcsLog.Info("Finished rescan")
|
rpcsLog.Info("Finished rescan")
|
||||||
|
|
Loading…
Reference in a new issue