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 }