Fix sync-and-exit option logic (#628)
* fix sync-and-exit logic * fix reading from doneSync channel * clean up * make statusd before using it * move syncAndStopNode to different file * change log level in travis chain sync command * do not use fmt but log * add progress log and set timeout to 20 mins * set datadir to .ethereumtest * fix datadir
This commit is contained in:
parent
d0ef64a177
commit
9885d74db0
|
@ -27,7 +27,9 @@ jobs:
|
|||
# to still run, but currently does not work due to a bug
|
||||
if: type != pull_request
|
||||
script:
|
||||
- ./build/bin/statusd -les -networkid 4 -sync-and-exit
|
||||
# sync the chain first; it will time out after 20 minutes; Rinkeby is networkid=4
|
||||
- make statusgo
|
||||
- ./build/bin/statusd -datadir .ethereumtest/Rinkeby -les -networkid=4 -sync-and-exit=20 -log WARN -standalone=false -discovery=false
|
||||
- make test-e2e networkid=4
|
||||
cache:
|
||||
directories:
|
||||
|
|
|
@ -114,17 +114,25 @@ func main() {
|
|||
|
||||
// Sync blockchain and stop.
|
||||
if *syncAndExit >= 0 {
|
||||
exitCode := syncAndStopNode(backend.NodeManager(), *syncAndExit)
|
||||
exitCode := syncAndStopNode(interruptCh, backend.NodeManager(), *syncAndExit)
|
||||
// Call was interrupted. Wait for graceful shutdown.
|
||||
if exitCode == -1 {
|
||||
if node, err := backend.NodeManager().Node(); err == nil && node != nil {
|
||||
node.Wait()
|
||||
}
|
||||
return
|
||||
}
|
||||
// Otherwise, exit immediately with a returned exit code.
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node, err := backend.NodeManager().Node()
|
||||
if err != nil {
|
||||
log.Fatalf("Getting node failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
// wait till node has been stopped
|
||||
node.Wait()
|
||||
}
|
||||
|
||||
|
@ -170,34 +178,6 @@ 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
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/status-im/status-go/geth/common"
|
||||
)
|
||||
|
||||
func createContextFromTimeout(timeout int) (context.Context, context.CancelFunc) {
|
||||
if timeout == 0 {
|
||||
return context.WithCancel(context.Background())
|
||||
}
|
||||
|
||||
return context.WithTimeout(context.Background(), time.Duration(timeout)*time.Minute)
|
||||
}
|
||||
|
||||
// syncAndStopNode tries to sync the blockchain and stop the node.
|
||||
// It returns an exit code (`0` if successful or `1` in case of error)
|
||||
// that can be used in `os.Exit` to exit immediately when the function returns.
|
||||
// The special exit code `-1` is used if execution was interrupted.
|
||||
func syncAndStopNode(interruptCh <-chan struct{}, nodeManager common.NodeManager, timeout int) (exitCode int) {
|
||||
log.Printf("syncAndStopNode: node will synchronize the chain and exit (timeout %d mins)", timeout)
|
||||
|
||||
ctx, cancel := createContextFromTimeout(timeout)
|
||||
defer cancel()
|
||||
|
||||
doneSync := make(chan struct{})
|
||||
errSync := make(chan error)
|
||||
go func() {
|
||||
if err := nodeManager.EnsureSync(ctx); err != nil {
|
||||
errSync <- err
|
||||
}
|
||||
close(doneSync)
|
||||
}()
|
||||
|
||||
select {
|
||||
case err := <-errSync:
|
||||
log.Printf("syncAndStopNode: failed to sync the chain: %v", err)
|
||||
exitCode = 1
|
||||
case <-doneSync:
|
||||
case <-interruptCh:
|
||||
// cancel context and return immediately if interrupted
|
||||
// `-1` is used as a special exit code to denote interruption
|
||||
return -1
|
||||
}
|
||||
|
||||
done, err := nodeManager.StopNode()
|
||||
if err != nil {
|
||||
log.Printf("syncAndStopNode: failed to stop the node: %v", err)
|
||||
return 1
|
||||
}
|
||||
<-done
|
||||
|
||||
return
|
||||
}
|
|
@ -532,25 +532,33 @@ func (m *NodeManager) EnsureSync(ctx context.Context) error {
|
|||
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()
|
||||
les, err := m.LightEthereumService()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get LES service: %v", err)
|
||||
}
|
||||
|
||||
downloader := les.Downloader()
|
||||
if downloader == nil {
|
||||
return errors.New("LightEthereumService downloader is nil")
|
||||
}
|
||||
|
||||
progress := downloader.Progress()
|
||||
if progress.CurrentBlock >= progress.HighestBlock {
|
||||
log.Debug("Synchronization completed")
|
||||
if m.PeerCount() > 0 && progress.CurrentBlock >= progress.HighestBlock {
|
||||
log.Debug("Synchronization completed", "current block", progress.CurrentBlock, "highest block", progress.HighestBlock)
|
||||
return nil
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(tickerResolution)
|
||||
defer ticker.Stop()
|
||||
|
||||
progressTicker := time.NewTicker(time.Minute)
|
||||
defer progressTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
|
@ -566,13 +574,13 @@ func (m *NodeManager) ensureSync(ctx context.Context) error {
|
|||
}
|
||||
progress = downloader.Progress()
|
||||
if progress.CurrentBlock >= progress.HighestBlock {
|
||||
log.Debug("Synchronization completed")
|
||||
log.Info("Synchronization completed", "current block", progress.CurrentBlock, "highest block", progress.HighestBlock)
|
||||
return nil
|
||||
}
|
||||
log.Debug(
|
||||
fmt.Sprintf("Synchronization is not finished yet: current block %d < highest block %d",
|
||||
progress.CurrentBlock, progress.HighestBlock),
|
||||
)
|
||||
log.Debug("Synchronization is not finished", "current", progress.CurrentBlock, "highest", progress.HighestBlock)
|
||||
case <-progressTicker.C:
|
||||
progress = downloader.Progress()
|
||||
log.Warn("Synchronization is not finished", "current", progress.CurrentBlock, "highest", progress.HighestBlock)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue