github.com/koko1123/flow-go-1@v0.29.6/engine/enqueue.go (about) 1 package engine 2 3 import ( 4 "fmt" 5 6 "github.com/rs/zerolog" 7 8 "github.com/koko1123/flow-go-1/model/flow" 9 "github.com/koko1123/flow-go-1/utils/logging" 10 ) 11 12 type Message struct { 13 OriginID flow.Identifier 14 Payload interface{} 15 } 16 17 // MessageStore is the interface to abstract how messages are buffered in memory before 18 // being handled by the engine 19 type MessageStore interface { 20 Put(*Message) bool 21 Get() (*Message, bool) 22 } 23 24 type Pattern struct { 25 // Match is a function to match a message to this pattern, typically by payload type. 26 Match MatchFunc 27 // Map is a function to apply to messages before storing them. If not provided, then the message is stored in its original form. 28 Map MapFunc 29 // Store is an abstract message store where we will store the message upon receipt. 30 Store MessageStore 31 } 32 33 type FilterFunc func(*Message) bool 34 35 type MatchFunc func(*Message) bool 36 37 type MapFunc func(*Message) (*Message, bool) 38 39 type MessageHandler struct { 40 log zerolog.Logger 41 notifier Notifier 42 patterns []Pattern 43 } 44 45 func NewMessageHandler(log zerolog.Logger, notifier Notifier, patterns ...Pattern) *MessageHandler { 46 return &MessageHandler{ 47 log: log.With().Str("component", "message_handler").Logger(), 48 notifier: notifier, 49 patterns: patterns, 50 } 51 } 52 53 // Process iterates over the internal processing patterns and determines if the payload matches. 54 // The _first_ matching pattern processes the payload. 55 // Returns 56 // - IncompatibleInputTypeError if no matching processor was found 57 // - All other errors are potential symptoms of internal state corruption or bugs (fatal). 58 func (e *MessageHandler) Process(originID flow.Identifier, payload interface{}) error { 59 msg := &Message{ 60 OriginID: originID, 61 Payload: payload, 62 } 63 64 for _, pattern := range e.patterns { 65 if pattern.Match(msg) { 66 var keep bool 67 if pattern.Map != nil { 68 msg, keep = pattern.Map(msg) 69 if !keep { 70 return nil 71 } 72 } 73 74 ok := pattern.Store.Put(msg) 75 if !ok { 76 e.log.Warn(). 77 Str("msg_type", logging.Type(payload)). 78 Hex("origin_id", originID[:]). 79 Msg("failed to store message - discarding") 80 return nil 81 } 82 e.notifier.Notify() 83 84 // message can only be matched by one pattern, and processed by one handler 85 return nil 86 } 87 } 88 89 return fmt.Errorf("no matching processor for message of type %T from origin %x: %w", payload, originID[:], IncompatibleInputTypeError) 90 } 91 92 func (e *MessageHandler) GetNotifier() <-chan struct{} { 93 return e.notifier.Channel() 94 }