github.com/koko1123/flow-go-1@v0.29.6/module/common.go (about)

     1  package module
     2  
     3  import (
     4  	"errors"
     5  	"sync"
     6  
     7  	"github.com/koko1123/flow-go-1/module/irrecoverable"
     8  )
     9  
    10  // WARNING: The semantics of this interface will be changing in the near future, with
    11  // startup / shutdown capabilities being delegated to the Startable interface instead.
    12  // For more details, see https://github.com/koko1123/flow-go-1/pull/1167
    13  //
    14  // ReadyDoneAware provides an easy interface to wait for module startup and shutdown.
    15  // Modules that implement this interface only support a single start-stop cycle, and
    16  // will not restart if Ready() is called again after shutdown has already commenced.
    17  type ReadyDoneAware interface {
    18  	// Ready commences startup of the module, and returns a ready channel that is closed once
    19  	// startup has completed. Note that the ready channel may never close if errors are
    20  	// encountered during startup.
    21  	// If shutdown has already commenced before this method is called for the first time,
    22  	// startup will not be performed and the returned channel will also never close.
    23  	// This should be an idempotent method.
    24  	Ready() <-chan struct{}
    25  
    26  	// Done commences shutdown of the module, and returns a done channel that is closed once
    27  	// shutdown has completed. Note that the done channel should be closed even if errors are
    28  	// encountered during shutdown.
    29  	// This should be an idempotent method.
    30  	Done() <-chan struct{}
    31  }
    32  
    33  // NoopReadyDoneAware is a ReadyDoneAware implementation whose ready/done channels close
    34  // immediately
    35  type NoopReadyDoneAware struct{}
    36  
    37  func (n *NoopReadyDoneAware) Ready() <-chan struct{} {
    38  	ready := make(chan struct{})
    39  	defer close(ready)
    40  	return ready
    41  }
    42  
    43  func (n *NoopReadyDoneAware) Done() <-chan struct{} {
    44  	done := make(chan struct{})
    45  	defer close(done)
    46  	return done
    47  }
    48  
    49  // ProxiedReadyDoneAware is a ReadyDoneAware implementation that proxies the ReadyDoneAware interface
    50  // from another implementation. This allows for usecases where the Ready/Done methods are needed before
    51  // the proxied object is initialized.
    52  type ProxiedReadyDoneAware struct {
    53  	ready chan struct{}
    54  	done  chan struct{}
    55  
    56  	initOnce sync.Once
    57  }
    58  
    59  // NewProxiedReadyDoneAware returns a new ProxiedReadyDoneAware instance
    60  func NewProxiedReadyDoneAware() *ProxiedReadyDoneAware {
    61  	return &ProxiedReadyDoneAware{
    62  		ready: make(chan struct{}),
    63  		done:  make(chan struct{}),
    64  	}
    65  }
    66  
    67  // Init adds the proxied ReadyDoneAware implementation and sets up the ready/done channels
    68  // to close when the respective channel on the proxied object closes.
    69  // Init can only be called once.
    70  //
    71  // IMPORTANT: the proxied ReadyDoneAware implementation must be idempotent since the Ready and Done
    72  // methods will be called immediately when calling Init.
    73  func (n *ProxiedReadyDoneAware) Init(rda ReadyDoneAware) {
    74  	n.initOnce.Do(func() {
    75  		go func() {
    76  			<-rda.Ready()
    77  			close(n.ready)
    78  		}()
    79  		go func() {
    80  			<-rda.Done()
    81  			close(n.done)
    82  		}()
    83  	})
    84  }
    85  
    86  func (n *ProxiedReadyDoneAware) Ready() <-chan struct{} {
    87  	return n.ready
    88  }
    89  
    90  func (n *ProxiedReadyDoneAware) Done() <-chan struct{} {
    91  	return n.done
    92  }
    93  
    94  var ErrMultipleStartup = errors.New("component may only be started once")
    95  
    96  // Startable provides an interface to start a component. Once started, the component
    97  // can be stopped by cancelling the given context.
    98  type Startable interface {
    99  	// Start starts the component. Any irrecoverable errors encountered while the component is running
   100  	// should be thrown with the given SignalerContext.
   101  	// This method should only be called once, and subsequent calls should panic with ErrMultipleStartup.
   102  	Start(irrecoverable.SignalerContext)
   103  }