github.com/argoproj/argo-events@v1.9.1/eventsources/sources/emitter/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 emitter
    18  
    19  import (
    20  	"context"
    21  	"encoding/json"
    22  	"fmt"
    23  	"time"
    24  
    25  	emitter "github.com/emitter-io/go/v2"
    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 Emitter event source
    39  type EventListener struct {
    40  	EventSourceName    string
    41  	EventName          string
    42  	EmitterEventSource v1alpha1.EmitterEventSource
    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.EmitterEvent
    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 Emitter event source...")
    66  	defer sources.Recover(el.GetEventName())
    67  
    68  	emitterEventSource := &el.EmitterEventSource
    69  
    70  	var options []func(client *emitter.Client)
    71  	if emitterEventSource.TLS != nil {
    72  		tlsConfig, err := common.GetTLSConfig(emitterEventSource.TLS)
    73  		if err != nil {
    74  			return fmt.Errorf("failed to get the tls configuration, %w", err)
    75  		}
    76  		options = append(options, emitter.WithTLSConfig(tlsConfig))
    77  	}
    78  	options = append(options, emitter.WithBrokers(emitterEventSource.Broker), emitter.WithAutoReconnect(true))
    79  
    80  	if emitterEventSource.Username != nil {
    81  		username, err := common.GetSecretFromVolume(emitterEventSource.Username)
    82  		if err != nil {
    83  			return fmt.Errorf("failed to retrieve the username from %s, %w", emitterEventSource.Username.Name, err)
    84  		}
    85  		options = append(options, emitter.WithUsername(username))
    86  	}
    87  
    88  	if emitterEventSource.Password != nil {
    89  		password, err := common.GetSecretFromVolume(emitterEventSource.Password)
    90  		if err != nil {
    91  			return fmt.Errorf("failed to retrieve the password from %s, %w", emitterEventSource.Password.Name, err)
    92  		}
    93  		options = append(options, emitter.WithPassword(password))
    94  	}
    95  
    96  	if emitterEventSource.JSONBody {
    97  		log.Info("assuming all events have a json body...")
    98  	}
    99  
   100  	log.Infow("creating a client", zap.Any("channelName", emitterEventSource.ChannelName))
   101  	client := emitter.NewClient(options...)
   102  
   103  	if err := common.DoWithRetry(emitterEventSource.ConnectionBackoff, func() error {
   104  		if err := client.Connect(); err != nil {
   105  			return err
   106  		}
   107  		return nil
   108  	}); err != nil {
   109  		return fmt.Errorf("failed to connect to %s, %w", emitterEventSource.Broker, err)
   110  	}
   111  
   112  	if err := client.Subscribe(emitterEventSource.ChannelKey, emitterEventSource.ChannelName, func(_ *emitter.Client, message emitter.Message) {
   113  		defer func(start time.Time) {
   114  			el.Metrics.EventProcessingDuration(el.GetEventSourceName(), el.GetEventName(), float64(time.Since(start)/time.Millisecond))
   115  		}(time.Now())
   116  
   117  		body := message.Payload()
   118  		event := &events.EmitterEventData{
   119  			Topic:    message.Topic(),
   120  			Body:     body,
   121  			Metadata: emitterEventSource.Metadata,
   122  		}
   123  		if emitterEventSource.JSONBody {
   124  			event.Body = (*json.RawMessage)(&body)
   125  		}
   126  		eventBytes, err := json.Marshal(event)
   127  
   128  		if err != nil {
   129  			log.Errorw("failed to marshal the event data", zap.Error(err))
   130  			el.Metrics.EventProcessingFailed(el.GetEventSourceName(), el.GetEventName())
   131  			return
   132  		}
   133  		log.Info("dispatching event on data channel...")
   134  		if err = dispatch(eventBytes); err != nil {
   135  			log.Errorw("failed to dispatch event", zap.Error(err))
   136  			el.Metrics.EventProcessingFailed(el.GetEventSourceName(), el.GetEventName())
   137  		}
   138  	}); err != nil {
   139  		return fmt.Errorf("failed to subscribe to channel %s, %w", emitterEventSource.ChannelName, err)
   140  	}
   141  
   142  	<-ctx.Done()
   143  
   144  	log.Infow("event source stopped, unsubscribe the channel", zap.Any("channelName", emitterEventSource.ChannelName))
   145  
   146  	if err := client.Unsubscribe(emitterEventSource.ChannelKey, emitterEventSource.ChannelName); err != nil {
   147  		log.Errorw("failed to unsubscribe", zap.Any("channelName", emitterEventSource.ChannelName), zap.Error(err))
   148  	}
   149  
   150  	return nil
   151  }