github.com/argoproj/argo-events@v1.9.1/eventsources/sources/azureservicebus/start.go (about) 1 package azureservicebus 2 3 import ( 4 "context" 5 "encoding/json" 6 "time" 7 8 "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 9 servicebus "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus" 10 "go.uber.org/zap" 11 12 "github.com/argoproj/argo-events/common" 13 "github.com/argoproj/argo-events/common/logging" 14 eventsourcecommon "github.com/argoproj/argo-events/eventsources/common" 15 "github.com/argoproj/argo-events/eventsources/sources" 16 metrics "github.com/argoproj/argo-events/metrics" 17 apicommon "github.com/argoproj/argo-events/pkg/apis/common" 18 "github.com/argoproj/argo-events/pkg/apis/events" 19 "github.com/argoproj/argo-events/pkg/apis/eventsource/v1alpha1" 20 ) 21 22 // EventListener implements Eventing for azure events hub event source 23 type EventListener struct { 24 EventSourceName string 25 EventName string 26 AzureServiceBusEventSource v1alpha1.AzureServiceBusEventSource 27 Metrics *metrics.Metrics 28 } 29 30 // GetEventSourceName returns name of event source 31 func (el *EventListener) GetEventSourceName() string { 32 return el.EventSourceName 33 } 34 35 // GetEventName returns name of event 36 func (el *EventListener) GetEventName() string { 37 return el.EventName 38 } 39 40 // GetEventSourceType return type of event server 41 func (el *EventListener) GetEventSourceType() apicommon.EventSourceType { 42 return apicommon.AzureServiceBus 43 } 44 45 type ReceiverType string 46 47 const ( 48 ReceiverTypeQueue ReceiverType = "queue" 49 ReceiverTypeSubscription ReceiverType = "subscription" 50 ) 51 52 // StartListening starts listening events 53 func (el *EventListener) StartListening(ctx context.Context, dispatch func([]byte, ...eventsourcecommon.Option) error) error { 54 log := logging.FromContext(ctx). 55 With(logging.LabelEventSourceType, el.GetEventSourceType(), logging.LabelEventName, el.GetEventName()) 56 57 log.Info("started processing the Azure Service Bus event source...") 58 defer sources.Recover(el.GetEventName()) 59 60 servicebusEventSource := &el.AzureServiceBusEventSource 61 clientOptions := servicebus.ClientOptions{} 62 if servicebusEventSource.TLS != nil { 63 tlsConfig, err := common.GetTLSConfig(servicebusEventSource.TLS) 64 if err != nil { 65 log.Errorw("failed to get the tls configuration", zap.Error(err)) 66 return err 67 } 68 clientOptions.TLSConfig = tlsConfig 69 } 70 var client *servicebus.Client 71 if servicebusEventSource.ConnectionString != nil { 72 log.Info("connecting to the service bus using connection string...") 73 connStr, err := common.GetSecretFromVolume(servicebusEventSource.ConnectionString) 74 if err != nil { 75 log.With("connection-string", servicebusEventSource.ConnectionString.Name).Errorw("failed to retrieve connection string from secret", zap.Error(err)) 76 return err 77 } 78 client, err = servicebus.NewClientFromConnectionString(connStr, &clientOptions) 79 if err != nil { 80 log.Errorw("failed to create a service bus client", zap.Error(err)) 81 return err 82 } 83 } else { 84 log.Info("connecting to azure queue storage with AAD credentials...") 85 cred, err := azidentity.NewDefaultAzureCredential(nil) 86 if err != nil { 87 log.Errorw("failed to create DefaultAzureCredential", zap.Error(err)) 88 return err 89 } 90 client, err = servicebus.NewClient(servicebusEventSource.FullyQualifiedNamespace, cred, &clientOptions) 91 if err != nil { 92 log.Errorw("failed to create a service bus client", zap.Error(err)) 93 return err 94 } 95 } 96 97 var receiver *servicebus.Receiver 98 var receiverType ReceiverType 99 var err error 100 101 if servicebusEventSource.QueueName != "" { 102 log.Info("creating a queue receiver...") 103 receiverType = ReceiverTypeQueue 104 receiver, err = client.NewReceiverForQueue(servicebusEventSource.QueueName, &servicebus.ReceiverOptions{ 105 ReceiveMode: servicebus.ReceiveModeReceiveAndDelete, 106 }) 107 } else { 108 log.Info("creating a subscription receiver...") 109 receiverType = ReceiverTypeSubscription 110 receiver, err = client.NewReceiverForSubscription(servicebusEventSource.TopicName, servicebusEventSource.SubscriptionName, &servicebus.ReceiverOptions{ 111 ReceiveMode: servicebus.ReceiveModeReceiveAndDelete, 112 }) 113 } 114 if err != nil { 115 if receiverType == ReceiverTypeQueue { 116 log.With("queue", servicebusEventSource.QueueName).Errorw("failed to create a queue receiver", zap.Error(err)) 117 } else { 118 log.With("topic", servicebusEventSource.TopicName, "subscription", servicebusEventSource.SubscriptionName).Errorw("failed to create a receiver for subscription", zap.Error(err)) 119 } 120 return err 121 } 122 123 if servicebusEventSource.JSONBody { 124 log.Info("assuming all events have a json body...") 125 } 126 127 for { 128 select { 129 case <-ctx.Done(): 130 log.Info("context has been cancelled, stopping the Azure Service Bus event source...") 131 if err := receiver.Close(ctx); err != nil { 132 log.Errorw("failed to close the receiver", zap.Error(err)) 133 return err 134 } 135 return nil 136 default: 137 messages, err := receiver.ReceiveMessages(ctx, 1, nil) 138 if err != nil { 139 log.Errorw("failed to receive messages", zap.Error(err)) 140 continue 141 } 142 143 for _, message := range messages { 144 if err := el.handleOne(servicebusEventSource, message, dispatch, log); err != nil { 145 if receiverType == ReceiverTypeQueue { 146 log.With("queue", servicebusEventSource.QueueName, "message_id", message.MessageID).Errorw("failed to process Azure Service Bus message", zap.Error(err)) 147 } else { 148 log.With("topic", servicebusEventSource.TopicName, "subscription", servicebusEventSource.SubscriptionName, "message_id", message.MessageID).Errorw("failed to process Azure Service Bus message", zap.Error(err)) 149 } 150 el.Metrics.EventProcessingFailed(el.GetEventSourceName(), el.GetEventName()) 151 continue 152 } 153 } 154 } 155 } 156 } 157 158 func (el *EventListener) handleOne(servicebusEventSource *v1alpha1.AzureServiceBusEventSource, message *servicebus.ReceivedMessage, dispatch func([]byte, ...eventsourcecommon.Option) error, log *zap.SugaredLogger) error { 159 defer func(start time.Time) { 160 el.Metrics.EventProcessingDuration(el.GetEventSourceName(), el.GetEventName(), float64(time.Since(start)/time.Millisecond)) 161 }(time.Now()) 162 163 log.Infow("received the message", zap.Any("message_id", message.MessageID)) 164 eventData := &events.AzureServiceBusEventData{ 165 ApplicationProperties: message.ApplicationProperties, 166 ContentType: message.ContentType, 167 CorrelationID: message.CorrelationID, 168 EnqueuedTime: message.EnqueuedTime, 169 MessageID: message.MessageID, 170 ReplyTo: message.ReplyTo, 171 SequenceNumber: message.SequenceNumber, 172 Subject: message.Subject, 173 Metadata: servicebusEventSource.Metadata, 174 } 175 176 if servicebusEventSource.JSONBody { 177 eventData.Body = (*json.RawMessage)(&message.Body) 178 } else { 179 eventData.Body = message.Body 180 } 181 182 eventBytes, err := json.Marshal(eventData) 183 if err != nil { 184 log.With("event_source", el.GetEventSourceName(), "event", el.GetEventName(), "message_id", message.MessageID).Errorw("failed to marshal the event data", zap.Error(err)) 185 return err 186 } 187 188 log.Info("dispatching the event to eventbus...") 189 if err = dispatch(eventBytes); err != nil { 190 log.With("event_source", el.GetEventSourceName(), "event", el.GetEventName(), "message_id", message.MessageID).Errorw("failed to dispatch the event", zap.Error(err)) 191 return err 192 } 193 194 return nil 195 }