github.com/koko1123/flow-go-1@v0.29.6/engine/access/relay/engine.go (about) 1 package relay 2 3 import ( 4 "fmt" 5 6 "github.com/rs/zerolog" 7 8 "github.com/koko1123/flow-go-1/engine" 9 "github.com/koko1123/flow-go-1/model/flow" 10 "github.com/koko1123/flow-go-1/network" 11 "github.com/koko1123/flow-go-1/network/channels" 12 ) 13 14 // Relay engine relays all the messages that are received to the given network for the corresponding channel 15 type Engine struct { 16 unit *engine.Unit // used to manage concurrency & shutdown 17 log zerolog.Logger // used to log relevant actions with context 18 conduits map[channels.Channel]network.Conduit // conduits for unstaked network 19 } 20 21 func New( 22 log zerolog.Logger, 23 channelList channels.ChannelList, 24 net network.Network, 25 unstakedNet network.Network, 26 ) (*Engine, error) { 27 e := &Engine{ 28 unit: engine.NewUnit(), 29 log: log.With().Str("engine", "relay").Logger(), 30 conduits: make(map[channels.Channel]network.Conduit), 31 } 32 33 for _, channel := range channelList { 34 _, err := net.Register(channel, e) 35 if err != nil { 36 return nil, fmt.Errorf("could not register relay engine on channel: %w", err) 37 } 38 39 conduit, err := unstakedNet.Register(channel, e) 40 if err != nil { 41 return nil, fmt.Errorf("could not register relay engine on unstaked network channel: %w", err) 42 } 43 e.conduits[channel] = conduit 44 } 45 46 return e, nil 47 } 48 49 // Ready returns a ready channel that is closed once the engine has fully 50 // started. 51 func (e *Engine) Ready() <-chan struct{} { 52 return e.unit.Ready() 53 } 54 55 // Done returns a done channel that is closed once the engine has fully stopped. 56 func (e *Engine) Done() <-chan struct{} { 57 return e.unit.Done() 58 } 59 60 // SubmitLocal submits an event originating on the local node. 61 func (e *Engine) SubmitLocal(event interface{}) { 62 e.unit.Launch(func() { 63 err := e.ProcessLocal(event) 64 if err != nil { 65 engine.LogError(e.log, err) 66 } 67 }) 68 } 69 70 // ProcessLocal processes an event originating on the local node. 71 func (e *Engine) ProcessLocal(event interface{}) error { 72 return e.unit.Do(func() error { 73 return fmt.Errorf("relay engine does not process local events") 74 }) 75 } 76 77 // Submit submits the given event from the node with the given origin ID 78 // for processing in a non-blocking manner. It returns instantly and logs 79 // a potential processing error internally when done. 80 func (e *Engine) Submit(channel channels.Channel, originID flow.Identifier, event interface{}) { 81 e.unit.Launch(func() { 82 err := e.Process(channel, originID, event) 83 if err != nil { 84 engine.LogError(e.log, err) 85 } 86 }) 87 } 88 89 // Process processes the given event from the node with the given origin ID 90 // in a blocking manner. It returns the potential processing error when 91 // done. 92 func (e *Engine) Process(channel channels.Channel, originID flow.Identifier, event interface{}) error { 93 return e.unit.Do(func() error { 94 return e.process(channel, originID, event) 95 }) 96 } 97 98 func (e *Engine) process(channel channels.Channel, originID flow.Identifier, event interface{}) error { 99 conduit, ok := e.conduits[channel] 100 101 if !ok { 102 return fmt.Errorf("received message on unknown channel %s", channel) 103 } 104 105 e.log.Trace().Interface("event", event).Str("channel", channel.String()).Str("originID", originID.String()).Msg("relaying message") 106 107 // We use a dummy target ID here so that events are broadcast to the entire network 108 if err := conduit.Publish(event, flow.ZeroID); err != nil { 109 return fmt.Errorf("could not relay message: %w", err) 110 } 111 112 return nil 113 }