Dmitry Shulyak 2d964bfe9f Remove async operations from node manager (#584)
The main goal of this change is to remove async operations from node manager.
Additionally all of the signals from node manager are moved to status backend.

All of the async operation now will have the following behaviour:
- If node in the correct state exit immediatly without error
- If node not in the correct state exit immediatly with error
- In all other cases spawn a goroutine with wanted operation
- All the progress regarding that operation will be reported
  by using signals
- Signals should be handled in once place, which is StatusBackend

There are 2 potentially breaking changes:
- Empty event field will be ommited when Envelope is sent to a client
- All errors will be delivered to a client as an Envelope, previously
  some errors (NodeExists, NoRunningNode) were delivered synchronously

Signed-off-by: Dmitry Shulyak <yashulyak@gmail.com>
2018-02-09 14:37:56 +01:00

55 lines
1.5 KiB
Go

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
}
if err := nodeManager.StopNode(); err != nil {
log.Printf("syncAndStopNode: failed to stop the node: %v", err)
return 1
}
return
}