github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/broker/federation/request_transformer.go (about)

     1  // Copyright (c) 2017-2021, R.I. Pienaar and the Choria Project contributors
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  
     5  package federation
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"github.com/choria-io/go-choria/broker/federation/stats"
    12  	"github.com/prometheus/client_golang/prometheus"
    13  	log "github.com/sirupsen/logrus"
    14  )
    15  
    16  func NewChoriaRequestTransformer(workers int, capacity int, broker *FederationBroker, logger *log.Entry) (*pooledWorker, error) {
    17  	worker, err := PooledWorkerFactory("choria_request_transformer", workers, Unconnected, capacity, broker, logger, func(ctx context.Context, self *pooledWorker, i int, logger *log.Entry) {
    18  		defer self.wg.Done()
    19  
    20  		workeri := fmt.Sprintf("%d", i)
    21  		rctr := stats.ReceivedMsgsCtr.WithLabelValues("choria_request_transformer", workeri, nameForConnectionMode(Unconnected), self.broker.Name, self.broker.identity)
    22  		ectr := stats.ErrorCtr.WithLabelValues("choria_request_transformer", workeri, nameForConnectionMode(Unconnected), self.broker.Name, self.broker.identity)
    23  		timer := stats.ProcessTime.WithLabelValues("choria_request_transformer", workeri, nameForConnectionMode(Unconnected), self.broker.Name, self.broker.identity)
    24  
    25  		workerf := func(cm chainmessage) {
    26  			obs := prometheus.NewTimer(timer)
    27  			defer obs.ObserveDuration()
    28  
    29  			req, federated := cm.Message.FederationRequestID()
    30  			if !federated {
    31  				logger.Errorf("Received a message from %s that is not federated", cm.Message.SenderID())
    32  				ectr.Inc()
    33  				return
    34  			}
    35  
    36  			targets, _ := cm.Message.FederationTargets()
    37  			if len(targets) == 0 {
    38  				logger.Errorf("Received a message %s from %s that does not have any targets", req, cm.Message.SenderID())
    39  				ectr.Inc()
    40  				return
    41  			}
    42  
    43  			replyto := cm.Message.ReplyTo()
    44  			if replyto == "" {
    45  				logger.Errorf("Received a message %s with no reply-to set", req)
    46  				ectr.Inc()
    47  				return
    48  			}
    49  
    50  			cm.Seen = append(cm.Seen, fmt.Sprintf("%s:%d", self.Name(), i))
    51  			cm.RequestID = req
    52  			cm.Targets = targets
    53  
    54  			cm.Message.SetFederationTargets([]string{})
    55  			cm.Message.SetFederationReplyTo(replyto)
    56  			cm.Message.SetReplyTo(fmt.Sprintf("choria.federation.%s.collective", self.broker.Name))
    57  
    58  			logger.Infof("Received request message '%s' via %s with %d targets", cm.RequestID, cm.Message.SenderID(), len(cm.Targets))
    59  
    60  			self.out <- cm
    61  
    62  			rctr.Inc()
    63  		}
    64  
    65  		for {
    66  			var cm chainmessage
    67  
    68  			select {
    69  			case cm = <-self.in:
    70  				workerf(cm)
    71  			case <-ctx.Done():
    72  				logger.Infof("Worker routine %s exiting", self.Name())
    73  				return
    74  			}
    75  
    76  		}
    77  	})
    78  
    79  	return worker, err
    80  }