93 lines
3.1 KiB
Go
93 lines
3.1 KiB
Go
package api
|
|
|
|
import (
|
|
"sync"
|
|
|
|
"github.com/golang/glog"
|
|
"github.com/linxGnu/grocksdb"
|
|
"github.com/trezor/blockbook/bchain"
|
|
"github.com/trezor/blockbook/db"
|
|
)
|
|
|
|
// refetch internal data
|
|
var refetchingInternalData = false
|
|
var refetchInternalDataMux sync.Mutex
|
|
|
|
func (w *Worker) IsRefetchingInternalData() bool {
|
|
refetchInternalDataMux.Lock()
|
|
defer refetchInternalDataMux.Unlock()
|
|
return refetchingInternalData
|
|
}
|
|
|
|
func (w *Worker) RefetchInternalData() error {
|
|
refetchInternalDataMux.Lock()
|
|
defer refetchInternalDataMux.Unlock()
|
|
if !refetchingInternalData {
|
|
refetchingInternalData = true
|
|
go w.RefetchInternalDataRoutine()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
const maxNumberOfRetires = 25
|
|
|
|
func (w *Worker) incrementRefetchInternalDataRetryCount(ie *db.BlockInternalDataError) {
|
|
wb := grocksdb.NewWriteBatch()
|
|
defer wb.Destroy()
|
|
err := w.db.StoreBlockInternalDataErrorEthereumType(wb, &bchain.Block{
|
|
BlockHeader: bchain.BlockHeader{
|
|
Hash: ie.Hash,
|
|
Height: ie.Height,
|
|
},
|
|
}, ie.ErrorMessage, ie.Retries+1)
|
|
if err != nil {
|
|
glog.Errorf("StoreBlockInternalDataErrorEthereumType %d %s, error %v", ie.Height, ie.Hash, err)
|
|
} else {
|
|
w.db.WriteBatch(wb)
|
|
}
|
|
}
|
|
|
|
func (w *Worker) RefetchInternalDataRoutine() {
|
|
internalErrors, err := w.db.GetBlockInternalDataErrorsEthereumType()
|
|
if err == nil {
|
|
for i := range internalErrors {
|
|
ie := &internalErrors[i]
|
|
if ie.Retries >= maxNumberOfRetires {
|
|
glog.Infof("Refetching internal data for %d %s, retries exceeded", ie.Height, ie.Hash)
|
|
continue
|
|
}
|
|
glog.Infof("Refetching internal data for %d %s, retries %d", ie.Height, ie.Hash, ie.Retries)
|
|
block, err := w.chain.GetBlock(ie.Hash, ie.Height)
|
|
var blockSpecificData *bchain.EthereumBlockSpecificData
|
|
if block != nil {
|
|
blockSpecificData, _ = block.CoinSpecificData.(*bchain.EthereumBlockSpecificData)
|
|
}
|
|
if err != nil || block == nil || blockSpecificData == nil || blockSpecificData.InternalDataError != "" {
|
|
glog.Errorf("Refetching internal data for %d %s, error %v, retrying", ie.Height, ie.Hash, err)
|
|
// try for second time to fetch the data - the 2nd attempt after the first unsuccessful has many times higher probability of success
|
|
// probably something to do with data preloaded to cache on the backend
|
|
block, err = w.chain.GetBlock(ie.Hash, ie.Height)
|
|
if err != nil || block == nil {
|
|
glog.Errorf("Refetching internal data for %d %s, error %v", ie.Height, ie.Hash, err)
|
|
continue
|
|
}
|
|
}
|
|
blockSpecificData, _ = block.CoinSpecificData.(*bchain.EthereumBlockSpecificData)
|
|
if blockSpecificData != nil && blockSpecificData.InternalDataError != "" {
|
|
glog.Errorf("Refetching internal data for %d %s, internal data error %v", ie.Height, ie.Hash, blockSpecificData.InternalDataError)
|
|
w.incrementRefetchInternalDataRetryCount(ie)
|
|
} else {
|
|
err = w.db.ReconnectInternalDataToBlockEthereumType(block)
|
|
if err != nil {
|
|
glog.Errorf("ReconnectInternalDataToBlockEthereumType %d %s, error %v", ie.Height, ie.Hash, err)
|
|
} else {
|
|
glog.Infof("Refetching internal data for %d %s, success", ie.Height, ie.Hash)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
refetchInternalDataMux.Lock()
|
|
refetchingInternalData = false
|
|
refetchInternalDataMux.Unlock()
|
|
}
|