mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-03 06:37:14 +00:00
service: remove stop method and use contexts (#7292)
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user