github.com/argoproj/argo-events@v1.9.1/eventsources/sources/azureeventshub/start.go (about)

     1  /*
     2  Copyright 2018 BlackRock, Inc.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package azureeventshub
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"time"
    24  
    25  	eventhub "github.com/Azure/azure-event-hubs-go/v3"
    26  	"go.uber.org/zap"
    27  
    28  	"github.com/argoproj/argo-events/common"
    29  	"github.com/argoproj/argo-events/common/logging"
    30  	eventsourcecommon "github.com/argoproj/argo-events/eventsources/common"
    31  	"github.com/argoproj/argo-events/eventsources/sources"
    32  	metrics "github.com/argoproj/argo-events/metrics"
    33  	apicommon "github.com/argoproj/argo-events/pkg/apis/common"
    34  	"github.com/argoproj/argo-events/pkg/apis/events"
    35  	"github.com/argoproj/argo-events/pkg/apis/eventsource/v1alpha1"
    36  )
    37  
    38  // EventListener implements Eventing for azure events hub event source
    39  type EventListener struct {
    40  	EventSourceName           string
    41  	EventName                 string
    42  	AzureEventsHubEventSource v1alpha1.AzureEventsHubEventSource
    43  	Metrics                   *metrics.Metrics
    44  }
    45  
    46  // GetEventSourceName returns name of event source
    47  func (el *EventListener) GetEventSourceName() string {
    48  	return el.EventSourceName
    49  }
    50  
    51  // GetEventName returns name of event
    52  func (el *EventListener) GetEventName() string {
    53  	return el.EventName
    54  }
    55  
    56  // GetEventSourceType return type of event server
    57  func (el *EventListener) GetEventSourceType() apicommon.EventSourceType {
    58  	return apicommon.AzureEventsHub
    59  }
    60  
    61  // StartListening starts listening events
    62  func (el *EventListener) StartListening(ctx context.Context, dispatch func([]byte, ...eventsourcecommon.Option) error) error {
    63  	log := logging.FromContext(ctx).
    64  		With(logging.LabelEventSourceType, el.GetEventSourceType(), logging.LabelEventName, el.GetEventName())
    65  	log.Info("started processing the Azure Events Hub event source...")
    66  	defer sources.Recover(el.GetEventName())
    67  
    68  	hubEventSource := &el.AzureEventsHubEventSource
    69  	log.Info("retrieving the shared access key name...")
    70  	sharedAccessKeyName, err := common.GetSecretFromVolume(hubEventSource.SharedAccessKeyName)
    71  	if err != nil {
    72  		return fmt.Errorf("failed to retrieve the shared access key name from secret %s, %w", hubEventSource.SharedAccessKeyName.Name, err)
    73  	}
    74  
    75  	log.Info("retrieving the shared access key...")
    76  	sharedAccessKey, err := common.GetSecretFromVolume(hubEventSource.SharedAccessKey)
    77  	if err != nil {
    78  		return fmt.Errorf("failed to retrieve the shared access key from secret %s, %w", hubEventSource.SharedAccessKey.Name, err)
    79  	}
    80  
    81  	endpoint := fmt.Sprintf("Endpoint=sb://%s/;SharedAccessKeyName=%s;SharedAccessKey=%s;EntityPath=%s", hubEventSource.FQDN, sharedAccessKeyName, sharedAccessKey, hubEventSource.HubName)
    82  
    83  	log.Info("connecting to the hub...")
    84  	hub, err := eventhub.NewHubFromConnectionString(endpoint)
    85  	if err != nil {
    86  		return fmt.Errorf("failed to connect to the hub %s, %w", hubEventSource.HubName, err)
    87  	}
    88  
    89  	handler := func(c context.Context, event *eventhub.Event) error {
    90  		defer func(start time.Time) {
    91  			el.Metrics.EventProcessingDuration(el.GetEventSourceName(), el.GetEventName(), float64(time.Since(start)/time.Millisecond))
    92  		}(time.Now())
    93  
    94  		log.Info("received an event from eventshub...")
    95  
    96  		eventData := &events.AzureEventsHubEventData{
    97  			Id:       event.ID,
    98  			Body:     event.Data,
    99  			Metadata: hubEventSource.Metadata,
   100  		}
   101  		if event.PartitionKey != nil {
   102  			eventData.PartitionKey = *event.PartitionKey
   103  		}
   104  
   105  		eventBytes, err := json.Marshal(eventData)
   106  		if err != nil {
   107  			el.Metrics.EventProcessingFailed(el.GetEventSourceName(), el.GetEventName())
   108  			return fmt.Errorf("failed to marshal the event data for event source %s and message id %s, %w", el.GetEventName(), event.ID, err)
   109  		}
   110  
   111  		log.Info("dispatching the event to eventbus...")
   112  		if err = dispatch(eventBytes); err != nil {
   113  			el.Metrics.EventProcessingFailed(el.GetEventSourceName(), el.GetEventName())
   114  			log.Errorw("failed to dispatch Azure EventHub event", zap.Error(err))
   115  			return err
   116  		}
   117  		return nil
   118  	}
   119  
   120  	// listen to each partition of the Event Hub
   121  	log.Info("gathering the hub runtime information...")
   122  	runtimeInfo, err := hub.GetRuntimeInformation(ctx)
   123  	if err != nil {
   124  		return fmt.Errorf("failed to get the hub runtime information for %s, %w", el.GetEventName(), err)
   125  	}
   126  
   127  	if runtimeInfo == nil {
   128  		return fmt.Errorf("runtime information is not available for %s, %w", el.GetEventName(), err)
   129  	}
   130  
   131  	if runtimeInfo.PartitionIDs == nil {
   132  		return fmt.Errorf("no partition ids are available for %s, %w", el.GetEventName(), err)
   133  	}
   134  
   135  	log.Info("handling the partitions...")
   136  	for _, partitionID := range runtimeInfo.PartitionIDs {
   137  		if _, err := hub.Receive(ctx, partitionID, handler, eventhub.ReceiveWithLatestOffset()); err != nil {
   138  			return fmt.Errorf("failed to receive events from partition %s, %w", partitionID, err)
   139  		}
   140  	}
   141  
   142  	<-ctx.Done()
   143  	log.Info("stopping listener handlers")
   144  
   145  	hub.Close(context.Background())
   146  
   147  	return nil
   148  }