parent
c00e5c9c58
commit
ca719af71c
|
@ -24,5 +24,5 @@
|
|||
"vet"
|
||||
],
|
||||
"Cyclo": 16,
|
||||
"Deadline": "100s"
|
||||
"Deadline": "200s"
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ jobs:
|
|||
# using fork == false may be preferred as it would allow PRs from the origin
|
||||
# to still run, but currently does not work due to a bug
|
||||
if: type != pull_request
|
||||
script: make test-e2e networkid=4
|
||||
script:
|
||||
- ./build/bin/statusd -les -networkid 4 -sync-and-exit
|
||||
- make test-e2e networkid=4
|
||||
cache:
|
||||
directories:
|
||||
- ".ethereumtest/Mainnet"
|
||||
|
|
|
@ -66,6 +66,8 @@ var (
|
|||
// Push Notification
|
||||
enablePN = flag.Bool("shh.notify", false, "Node is capable of sending Push Notifications")
|
||||
firebaseAuth = flag.String("shh.firebaseauth", "", "FCM Authorization Key used for sending Push Notifications")
|
||||
|
||||
syncAndExit = flag.Int("sync-and-exit", -1, "Timeout in minutes for blockchain sync and exit, zero means no timeout unless sync is finished")
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -110,6 +112,12 @@ func main() {
|
|||
go startCollectingStats(interruptCh, backend.NodeManager())
|
||||
}
|
||||
|
||||
// Sync blockchain and stop.
|
||||
if *syncAndExit >= 0 {
|
||||
exitCode := syncAndStopNode(backend.NodeManager(), *syncAndExit)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := backend.NodeManager().Node()
|
||||
if err != nil {
|
||||
|
@ -162,6 +170,34 @@ func startCollectingStats(interruptCh <-chan struct{}, nodeManager common.NodeMa
|
|||
}
|
||||
}
|
||||
|
||||
func syncAndStopNode(nodeManager common.NodeManager, timeout int) (exitCode int) {
|
||||
log.Println("Node will synchronize and exit")
|
||||
if timeout < 0 {
|
||||
log.Println("Sync and stop error: negative timeout value")
|
||||
return 1
|
||||
}
|
||||
var err error
|
||||
if timeout == 0 {
|
||||
err = nodeManager.EnsureSync(context.Background())
|
||||
} else {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), (time.Duration)(timeout)*time.Minute)
|
||||
err = nodeManager.EnsureSync(ctx)
|
||||
defer cancel()
|
||||
}
|
||||
if err != nil {
|
||||
log.Printf("Sync error: %v", err)
|
||||
exitCode = 1
|
||||
}
|
||||
var done <-chan struct{}
|
||||
done, err = nodeManager.StopNode()
|
||||
if err != nil {
|
||||
log.Printf("Stop node err: %v", err)
|
||||
return 1
|
||||
}
|
||||
<-done
|
||||
return
|
||||
}
|
||||
|
||||
// makeNodeConfig parses incoming CLI options and returns node configuration object
|
||||
func makeNodeConfig() (*params.NodeConfig, error) {
|
||||
devMode := !*prodMode
|
||||
|
|
|
@ -53,6 +53,9 @@ type NodeManager interface {
|
|||
// Stopped node cannot be resumed, one starts a new node instead.
|
||||
StopNode() (<-chan struct{}, error)
|
||||
|
||||
// EnsureSync waits until blockchain is synchronized.
|
||||
EnsureSync(ctx context.Context) error
|
||||
|
||||
// RestartNode restart running Status node, fails if node is not running
|
||||
RestartNode() (<-chan struct{}, error)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
context "context"
|
||||
accounts "github.com/ethereum/go-ethereum/accounts"
|
||||
keystore "github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
common "github.com/ethereum/go-ethereum/common"
|
||||
|
@ -67,6 +68,18 @@ func (mr *MockNodeManagerMockRecorder) StopNode() *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StopNode", reflect.TypeOf((*MockNodeManager)(nil).StopNode))
|
||||
}
|
||||
|
||||
// EnsureSync mocks base method
|
||||
func (m *MockNodeManager) EnsureSync(ctx context.Context) error {
|
||||
ret := m.ctrl.Call(m, "EnsureSync", ctx)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// EnsureSync indicates an expected call of EnsureSync
|
||||
func (mr *MockNodeManagerMockRecorder) EnsureSync(ctx interface{}) *gomock.Call {
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureSync", reflect.TypeOf((*MockNodeManager)(nil).EnsureSync), ctx)
|
||||
}
|
||||
|
||||
// RestartNode mocks base method
|
||||
func (m *MockNodeManager) RestartNode() (<-chan struct{}, error) {
|
||||
ret := m.ctrl.Call(m, "RestartNode")
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
|
@ -518,3 +520,59 @@ func (m *NodeManager) isNodeAvailable() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
// tickerResolution is the delta to check blockchain sync progress.
|
||||
const tickerResolution = time.Second
|
||||
|
||||
// EnsureSync waits until blockchain synchronization
|
||||
// is complete and returns.
|
||||
func (m *NodeManager) EnsureSync(ctx context.Context) error {
|
||||
// Don't wait for any blockchain sync for the
|
||||
// local private chain as blocks are never mined.
|
||||
if m.config.NetworkID == params.StatusChainNetworkID {
|
||||
return nil
|
||||
}
|
||||
if m.lesService == nil {
|
||||
return errors.New("LightEthereumService is nil")
|
||||
}
|
||||
return m.ensureSync(ctx)
|
||||
}
|
||||
|
||||
func (m *NodeManager) ensureSync(ctx context.Context) error {
|
||||
downloader := m.lesService.Downloader()
|
||||
if downloader == nil {
|
||||
return errors.New("LightEthereumService downloader is nil")
|
||||
}
|
||||
progress := downloader.Progress()
|
||||
if progress.CurrentBlock >= progress.HighestBlock {
|
||||
log.Debug("Synchronization completed")
|
||||
return nil
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(tickerResolution)
|
||||
defer ticker.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return errors.New("timeout during node synchronization")
|
||||
case <-ticker.C:
|
||||
if m.PeerCount() == 0 {
|
||||
log.Debug("No established connections with any peers, continue waiting for a sync")
|
||||
continue
|
||||
}
|
||||
if downloader.Synchronising() {
|
||||
log.Debug("Synchronization is in progress")
|
||||
continue
|
||||
}
|
||||
progress = downloader.Progress()
|
||||
if progress.CurrentBlock >= progress.HighestBlock {
|
||||
log.Debug("Synchronization completed")
|
||||
return nil
|
||||
}
|
||||
log.Debug(
|
||||
fmt.Sprintf("Synchronization is not finished yet: current block %d < highest block %d",
|
||||
progress.CurrentBlock, progress.HighestBlock),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue