From 35c1a4895e81f6506e98cdf7d0151c6bcdceea67 Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Mon, 16 Dec 2019 14:22:09 +0100 Subject: [PATCH] crdt consensus: do not panic when getting the state while not ready. Wait instead. --- consensus/crdt/consensus.go | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/consensus/crdt/consensus.go b/consensus/crdt/consensus.go index 6a13c60e..ae8d62b2 100644 --- a/consensus/crdt/consensus.go +++ b/consensus/crdt/consensus.go @@ -67,9 +67,10 @@ type Consensus struct { dht *dht.IpfsDHT pubsub *pubsub.PubSub - rpcClient *rpc.Client - rpcReady chan struct{} - readyCh chan struct{} + rpcClient *rpc.Client + rpcReady chan struct{} + stateReady chan struct{} + readyCh chan struct{} shutdownLock sync.RWMutex shutdown bool @@ -124,6 +125,7 @@ func New( pubsub: pubsub, rpcReady: make(chan struct{}, 1), readyCh: make(chan struct{}, 1), + stateReady: make(chan struct{}, 1), } go css.setup() @@ -263,6 +265,8 @@ func (css *Consensus) setup() { logger.Info("'trust all' mode enabled. Any peer in the cluster can modify the pinset.") } + // notifies State() it is safe to return + close(css.stateReady) css.readyCh <- struct{}{} } @@ -427,8 +431,18 @@ func (css *Consensus) RmPeer(ctx context.Context, pid peer.ID) error { return ErrRmPeer } -// State returns the cluster shared state. -func (css *Consensus) State(ctx context.Context) (state.ReadOnly, error) { return css.state, nil } +// State returns the cluster shared state. It will block until the consensus +// component is ready, shutdown or the given context has been cancelled. +func (css *Consensus) State(ctx context.Context) (state.ReadOnly, error) { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case <-css.ctx.Done(): + return nil, ctx.Err() + case <-css.stateReady: + return css.state, nil + } +} // Clean deletes all crdt-consensus datas from the datastore. func (css *Consensus) Clean(ctx context.Context) error {