service: remove stop method and use contexts (#7292)

This commit is contained in:
Sam Kleinman
2021-11-18 17:56:21 -05:00
committed by GitHub
parent 1c34d17240
commit 6ab62fe7b6
115 changed files with 3613 additions and 2271 deletions
+8 -7
View File
@@ -1,6 +1,7 @@
package blocksync
import (
"context"
"errors"
"fmt"
"math"
@@ -116,15 +117,15 @@ func NewBlockPool(
// OnStart implements service.Service by spawning requesters routine and recording
// pool's start time.
func (pool *BlockPool) OnStart() error {
func (pool *BlockPool) OnStart(ctx context.Context) error {
pool.lastAdvance = time.Now()
pool.lastHundredBlockTimeStamp = pool.lastAdvance
go pool.makeRequestersRoutine()
go pool.makeRequestersRoutine(ctx)
return nil
}
// spawns requesters as needed
func (pool *BlockPool) makeRequestersRoutine() {
func (pool *BlockPool) makeRequestersRoutine(ctx context.Context) {
for {
if !pool.IsRunning() {
break
@@ -144,7 +145,7 @@ func (pool *BlockPool) makeRequestersRoutine() {
pool.removeTimedoutPeers()
default:
// request for more blocks.
pool.makeNextRequester()
pool.makeNextRequester(ctx)
}
}
}
@@ -397,7 +398,7 @@ func (pool *BlockPool) pickIncrAvailablePeer(height int64) *bpPeer {
return nil
}
func (pool *BlockPool) makeNextRequester() {
func (pool *BlockPool) makeNextRequester(ctx context.Context) {
pool.mtx.Lock()
defer pool.mtx.Unlock()
@@ -411,7 +412,7 @@ func (pool *BlockPool) makeNextRequester() {
pool.requesters[nextHeight] = request
atomic.AddInt32(&pool.numPending, 1)
err := request.Start()
err := request.Start(ctx)
if err != nil {
request.Logger.Error("Error starting request", "err", err)
}
@@ -570,7 +571,7 @@ func newBPRequester(pool *BlockPool, height int64) *bpRequester {
return bpr
}
func (bpr *bpRequester) OnStart() error {
func (bpr *bpRequester) OnStart(ctx context.Context) error {
go bpr.requestRoutine()
return nil
}
+16 -19
View File
@@ -1,6 +1,7 @@
package blocksync
import (
"context"
"fmt"
mrand "math/rand"
"testing"
@@ -78,22 +79,20 @@ func makePeers(numPeers int, minHeight, maxHeight int64) testPeers {
}
func TestBlockPoolBasic(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
start := int64(42)
peers := makePeers(10, start+1, 1000)
errorsCh := make(chan peerError, 1000)
requestsCh := make(chan BlockRequest, 1000)
pool := NewBlockPool(log.TestingLogger(), start, requestsCh, errorsCh)
err := pool.Start()
if err != nil {
if err := pool.Start(ctx); err != nil {
t.Error(err)
}
t.Cleanup(func() {
if err := pool.Stop(); err != nil {
t.Error(err)
}
})
t.Cleanup(func() { cancel(); pool.Wait() })
peers.start()
defer peers.stop()
@@ -137,20 +136,19 @@ func TestBlockPoolBasic(t *testing.T) {
}
func TestBlockPoolTimeout(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
start := int64(42)
peers := makePeers(10, start+1, 1000)
errorsCh := make(chan peerError, 1000)
requestsCh := make(chan BlockRequest, 1000)
pool := NewBlockPool(log.TestingLogger(), start, requestsCh, errorsCh)
err := pool.Start()
err := pool.Start(ctx)
if err != nil {
t.Error(err)
}
t.Cleanup(func() {
if err := pool.Stop(); err != nil {
t.Error(err)
}
})
t.Cleanup(func() { cancel(); pool.Wait() })
for _, peer := range peers {
t.Logf("Peer %v", peer.id)
@@ -199,6 +197,9 @@ func TestBlockPoolTimeout(t *testing.T) {
}
func TestBlockPoolRemovePeer(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
peers := make(testPeers, 10)
for i := 0; i < 10; i++ {
peerID := types.NodeID(fmt.Sprintf("%d", i+1))
@@ -209,13 +210,9 @@ func TestBlockPoolRemovePeer(t *testing.T) {
errorsCh := make(chan peerError)
pool := NewBlockPool(log.TestingLogger(), 1, requestsCh, errorsCh)
err := pool.Start()
err := pool.Start(ctx)
require.NoError(t, err)
t.Cleanup(func() {
if err := pool.Stop(); err != nil {
t.Error(err)
}
})
t.Cleanup(func() { cancel(); pool.Wait() })
// add peers
for peerID, peer := range peers {
+19 -6
View File
@@ -1,6 +1,7 @@
package blocksync
import (
"context"
"fmt"
"runtime/debug"
"sync"
@@ -49,7 +50,7 @@ func GetChannelDescriptor() *p2p.ChannelDescriptor {
type consensusReactor interface {
// For when we switch from block sync reactor to the consensus
// machine.
SwitchToConsensus(state sm.State, skipWAL bool)
SwitchToConsensus(ctx context.Context, state sm.State, skipWAL bool)
}
type peerError struct {
@@ -151,9 +152,9 @@ func NewReactor(
//
// If blockSync is enabled, we also start the pool and the pool processing
// goroutine. If the pool fails to start, an error is returned.
func (r *Reactor) OnStart() error {
func (r *Reactor) OnStart(ctx context.Context) error {
if r.blockSync.IsSet() {
if err := r.pool.Start(); err != nil {
if err := r.pool.Start(ctx); err != nil {
return err
}
r.poolWG.Add(1)
@@ -362,12 +363,12 @@ func (r *Reactor) processPeerUpdates() {
// SwitchToBlockSync is called by the state sync reactor when switching to fast
// sync.
func (r *Reactor) SwitchToBlockSync(state sm.State) error {
func (r *Reactor) SwitchToBlockSync(ctx context.Context, state sm.State) error {
r.blockSync.Set()
r.initialState = state
r.pool.height = state.LastBlockHeight + 1
if err := r.pool.Start(); err != nil {
if err := r.pool.Start(ctx); err != nil {
return err
}
@@ -423,6 +424,17 @@ func (r *Reactor) requestRoutine() {
}
}
func (r *Reactor) stopCtx() context.Context {
ctx, cancel := context.WithCancel(context.Background())
go func() {
<-r.closeCh
cancel()
}()
return ctx
}
// poolRoutine handles messages from the poolReactor telling the reactor what to
// do.
//
@@ -441,6 +453,7 @@ func (r *Reactor) poolRoutine(stateSynced bool) {
lastRate = 0.0
didProcessCh = make(chan struct{}, 1)
ctx = r.stopCtx()
)
defer trySyncTicker.Stop()
@@ -488,7 +501,7 @@ FOR_LOOP:
r.blockSync.UnSet()
if r.consReactor != nil {
r.consReactor.SwitchToConsensus(state, blocksSynced > 0 || stateSynced)
r.consReactor.SwitchToConsensus(ctx, state, blocksSynced > 0 || stateSynced)
}
break FOR_LOOP
+34 -13
View File
@@ -1,6 +1,7 @@
package blocksync
import (
"context"
"os"
"testing"
"time"
@@ -41,6 +42,7 @@ type reactorTestSuite struct {
}
func setup(
ctx context.Context,
t *testing.T,
genDoc *types.GenesisDoc,
privVal types.PrivValidator,
@@ -49,13 +51,16 @@ func setup(
) *reactorTestSuite {
t.Helper()
var cancel context.CancelFunc
ctx, cancel = context.WithCancel(ctx)
numNodes := len(maxBlockHeights)
require.True(t, numNodes >= 1,
"must specify at least one block height (nodes)")
rts := &reactorTestSuite{
logger: log.TestingLogger().With("module", "block_sync", "testCase", t.Name()),
network: p2ptest.MakeNetwork(t, p2ptest.NetworkOptions{NumNodes: numNodes}),
network: p2ptest.MakeNetwork(ctx, t, p2ptest.NetworkOptions{NumNodes: numNodes}),
nodes: make([]types.NodeID, 0, numNodes),
reactors: make(map[types.NodeID]*Reactor, numNodes),
app: make(map[types.NodeID]proxy.AppConns, numNodes),
@@ -70,17 +75,19 @@ func setup(
i := 0
for nodeID := range rts.network.Nodes {
rts.addNode(t, nodeID, genDoc, privVal, maxBlockHeights[i])
rts.addNode(ctx, t, nodeID, genDoc, privVal, maxBlockHeights[i])
i++
}
t.Cleanup(func() {
cancel()
for _, nodeID := range rts.nodes {
rts.peerUpdates[nodeID].Close()
if rts.reactors[nodeID].IsRunning() {
require.NoError(t, rts.reactors[nodeID].Stop())
require.NoError(t, rts.app[nodeID].Stop())
rts.reactors[nodeID].Wait()
rts.app[nodeID].Wait()
require.False(t, rts.reactors[nodeID].IsRunning())
}
}
@@ -89,7 +96,9 @@ func setup(
return rts
}
func (rts *reactorTestSuite) addNode(t *testing.T,
func (rts *reactorTestSuite) addNode(
ctx context.Context,
t *testing.T,
nodeID types.NodeID,
genDoc *types.GenesisDoc,
privVal types.PrivValidator,
@@ -101,7 +110,7 @@ func (rts *reactorTestSuite) addNode(t *testing.T,
rts.nodes = append(rts.nodes, nodeID)
rts.app[nodeID] = proxy.NewAppConns(abciclient.NewLocalCreator(&abci.BaseApplication{}), logger, proxy.NopMetrics())
require.NoError(t, rts.app[nodeID].Start())
require.NoError(t, rts.app[nodeID].Start(ctx))
blockDB := dbm.NewMemDB()
stateDB := dbm.NewMemDB()
@@ -170,7 +179,7 @@ func (rts *reactorTestSuite) addNode(t *testing.T,
consensus.NopMetrics())
require.NoError(t, err)
require.NoError(t, rts.reactors[nodeID].Start())
require.NoError(t, rts.reactors[nodeID].Start(ctx))
require.True(t, rts.reactors[nodeID].IsRunning())
}
@@ -184,6 +193,9 @@ func (rts *reactorTestSuite) start(t *testing.T) {
}
func TestReactor_AbruptDisconnect(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cfg, err := config.ResetTestRoot("block_sync_reactor_test")
require.NoError(t, err)
defer os.RemoveAll(cfg.RootDir)
@@ -191,7 +203,7 @@ func TestReactor_AbruptDisconnect(t *testing.T) {
genDoc, privVals := factory.RandGenesisDoc(cfg, 1, false, 30)
maxBlockHeight := int64(64)
rts := setup(t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
require.Equal(t, maxBlockHeight, rts.reactors[rts.nodes[0]].store.Height())
@@ -220,6 +232,9 @@ func TestReactor_AbruptDisconnect(t *testing.T) {
}
func TestReactor_SyncTime(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cfg, err := config.ResetTestRoot("block_sync_reactor_test")
require.NoError(t, err)
defer os.RemoveAll(cfg.RootDir)
@@ -227,7 +242,7 @@ func TestReactor_SyncTime(t *testing.T) {
genDoc, privVals := factory.RandGenesisDoc(cfg, 1, false, 30)
maxBlockHeight := int64(101)
rts := setup(t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
require.Equal(t, maxBlockHeight, rts.reactors[rts.nodes[0]].store.Height())
rts.start(t)
@@ -244,6 +259,9 @@ func TestReactor_SyncTime(t *testing.T) {
}
func TestReactor_NoBlockResponse(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cfg, err := config.ResetTestRoot("block_sync_reactor_test")
require.NoError(t, err)
@@ -252,7 +270,7 @@ func TestReactor_NoBlockResponse(t *testing.T) {
genDoc, privVals := factory.RandGenesisDoc(cfg, 1, false, 30)
maxBlockHeight := int64(65)
rts := setup(t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0}, 0)
require.Equal(t, maxBlockHeight, rts.reactors[rts.nodes[0]].store.Height())
@@ -293,6 +311,9 @@ func TestReactor_BadBlockStopsPeer(t *testing.T) {
// See: https://github.com/tendermint/tendermint/issues/6005
t.SkipNow()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cfg, err := config.ResetTestRoot("block_sync_reactor_test")
require.NoError(t, err)
defer os.RemoveAll(cfg.RootDir)
@@ -300,7 +321,7 @@ func TestReactor_BadBlockStopsPeer(t *testing.T) {
maxBlockHeight := int64(48)
genDoc, privVals := factory.RandGenesisDoc(cfg, 1, false, 30)
rts := setup(t, genDoc, privVals[0], []int64{maxBlockHeight, 0, 0, 0, 0}, 1000)
rts := setup(ctx, t, genDoc, privVals[0], []int64{maxBlockHeight, 0, 0, 0, 0}, 1000)
require.Equal(t, maxBlockHeight, rts.reactors[rts.nodes[0]].store.Height())
@@ -333,11 +354,11 @@ func TestReactor_BadBlockStopsPeer(t *testing.T) {
// XXX: This causes a potential race condition.
// See: https://github.com/tendermint/tendermint/issues/6005
otherGenDoc, otherPrivVals := factory.RandGenesisDoc(cfg, 1, false, 30)
newNode := rts.network.MakeNode(t, p2ptest.NodeOptions{
newNode := rts.network.MakeNode(ctx, t, p2ptest.NodeOptions{
MaxPeers: uint16(len(rts.nodes) + 1),
MaxConnected: uint16(len(rts.nodes) + 1),
})
rts.addNode(t, newNode.NodeID, otherGenDoc, otherPrivVals[0], maxBlockHeight)
rts.addNode(ctx, t, newNode.NodeID, otherGenDoc, otherPrivVals[0], maxBlockHeight)
// add a fake peer just so we do not wait for the consensus ticker to timeout
rts.reactors[newNode.NodeID].pool.SetPeerRange("00ff", 10, 10)