github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/network/underlay/internal/readSubscription.go (about) 1 package internal 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "strings" 8 9 "github.com/libp2p/go-libp2p/core/peer" 10 11 "github.com/rs/zerolog" 12 13 "github.com/onflow/flow-go/network/message" 14 "github.com/onflow/flow-go/network/p2p" 15 validator "github.com/onflow/flow-go/network/validator/pubsub" 16 "github.com/onflow/flow-go/utils/logging" 17 ) 18 19 // ReadSubscriptionCallBackFunction the callback called when a new message is received on the read subscription 20 type ReadSubscriptionCallBackFunction func(msg *message.Message, peerID peer.ID) 21 22 // ReadSubscription reads the messages coming in on the subscription and calls the given callback until 23 // the context of the subscription is cancelled. 24 type ReadSubscription struct { 25 log zerolog.Logger 26 sub p2p.Subscription 27 callback ReadSubscriptionCallBackFunction 28 } 29 30 // NewReadSubscription reads the messages coming in on the subscription 31 func NewReadSubscription(sub p2p.Subscription, callback ReadSubscriptionCallBackFunction, log zerolog.Logger) *ReadSubscription { 32 r := ReadSubscription{ 33 log: log.With().Str("channel", sub.Topic()).Logger(), 34 sub: sub, 35 callback: callback, 36 } 37 38 return &r 39 } 40 41 // ReceiveLoop must be run in a goroutine. It continuously receives 42 // messages for the topic and calls the callback synchronously 43 func (r *ReadSubscription) ReceiveLoop(ctx context.Context) { 44 defer r.log.Debug().Msg("exiting receive routine") 45 46 for { 47 // read the next message from libp2p's subscription (blocking call) 48 rawMsg, err := r.sub.Next(ctx) 49 50 if err != nil { 51 // network may have cancelled the context 52 if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) { 53 return 54 } 55 56 // subscription may have just been cancelled if node is being stopped or the topic has been unsubscribed, 57 // don't log error in that case 58 // (https://github.com/ipsn/go-ipfs/blob/master/gxlibs/github.com/libp2p/go-libp2p-pubsub/pubsub.go#L435) 59 if strings.Contains(err.Error(), "subscription cancelled") { 60 return 61 } 62 63 // log any other error 64 r.log.Err(err).Msg("failed to read subscription message") 65 66 return 67 } 68 69 validatorData, ok := rawMsg.ValidatorData.(validator.TopicValidatorData) 70 if !ok { 71 r.log.Error(). 72 Str("raw_msg", rawMsg.String()). 73 Bool(logging.KeySuspicious, true). 74 Str("received_validator_data_type", fmt.Sprintf("%T", rawMsg.ValidatorData)). 75 Msg("[BUG] validator data missing!") 76 return 77 } 78 79 // call the callback 80 r.callback(validatorData.Message, validatorData.From) 81 } 82 }