github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/service/broker/handler/handler.go (about)

     1  package handler
     2  
     3  import (
     4  	"context"
     5  
     6  	pb "github.com/tickoalcantara12/micro/v3/proto/broker"
     7  	"github.com/tickoalcantara12/micro/v3/service/auth"
     8  	"github.com/tickoalcantara12/micro/v3/service/broker"
     9  	"github.com/tickoalcantara12/micro/v3/service/context/metadata"
    10  	"github.com/tickoalcantara12/micro/v3/service/errors"
    11  	"github.com/tickoalcantara12/micro/v3/service/logger"
    12  	authns "github.com/tickoalcantara12/micro/v3/util/auth/namespace"
    13  )
    14  
    15  type Broker struct{}
    16  
    17  func (h *Broker) Publish(ctx context.Context, req *pb.PublishRequest, rsp *pb.Empty) error {
    18  	// authorize the request
    19  	acc, ok := auth.AccountFromContext(ctx)
    20  	if !ok {
    21  		return errors.Unauthorized("broker.Broker.Publish", authns.ErrForbidden.Error())
    22  	}
    23  
    24  	// validate the request
    25  	if req.Message == nil {
    26  		return errors.BadRequest("broker.Broker.Publish", "Missing message")
    27  	}
    28  
    29  	// ensure the header is not nil
    30  	if req.Message.Header == nil {
    31  		req.Message.Header = map[string]string{}
    32  	}
    33  
    34  	// set any headers which aren't already set
    35  	if md, ok := metadata.FromContext(ctx); ok {
    36  		for k, v := range md {
    37  			if _, ok := req.Message.Header[k]; !ok {
    38  				req.Message.Header[k] = v
    39  			}
    40  		}
    41  	}
    42  
    43  	logger.Debugf("Publishing message to %s topic in the %v namespace", req.Topic, acc.Issuer)
    44  	err := broker.DefaultBroker.Publish(acc.Issuer+"."+req.Topic, &broker.Message{
    45  		Header: req.Message.Header,
    46  		Body:   req.Message.Body,
    47  	})
    48  	logger.Debugf("Published message to %s topic in the %v namespace", req.Topic, acc.Issuer)
    49  	if err != nil {
    50  		return errors.InternalServerError("broker.Broker.Publish", err.Error())
    51  	}
    52  	return nil
    53  }
    54  
    55  func (h *Broker) Subscribe(ctx context.Context, req *pb.SubscribeRequest, stream pb.Broker_SubscribeStream) error {
    56  	// authorize the request
    57  	acc, ok := auth.AccountFromContext(ctx)
    58  	if !ok {
    59  		return errors.Unauthorized("broker.Broker.Subscribe", authns.ErrForbidden.Error())
    60  	}
    61  	ns := acc.Issuer
    62  
    63  	if len(req.Topic) == 0 {
    64  		return errors.BadRequest("broker.Broker.Subscribe", "Missing topic")
    65  	}
    66  	errChan := make(chan error, 1)
    67  
    68  	// message Broker to stream back messages from broker
    69  	Broker := func(m *broker.Message) error {
    70  		if err := stream.Send(&pb.Message{
    71  			Header: m.Header,
    72  			Body:   m.Body,
    73  		}); err != nil {
    74  			select {
    75  			case errChan <- err:
    76  				return err
    77  			default:
    78  				return err
    79  			}
    80  		}
    81  		return nil
    82  	}
    83  
    84  	logger.Debugf("Subscribing to %s topic in namespace %v", req.Topic, ns)
    85  	opts := []broker.SubscribeOption{}
    86  	if len(req.Queue) > 0 {
    87  		opts = append(opts, broker.Queue(req.Queue))
    88  	}
    89  	sub, err := broker.DefaultBroker.Subscribe(ns+"."+req.Topic, Broker, opts...)
    90  	if err != nil {
    91  		return errors.InternalServerError("broker.Broker.Subscribe", err.Error())
    92  	}
    93  	defer func() {
    94  		logger.Debugf("Unsubscribing from topic %s in namespace %v", req.Topic, ns)
    95  		sub.Unsubscribe()
    96  	}()
    97  
    98  	select {
    99  	case <-ctx.Done():
   100  		logger.Debugf("Context done for subscription to topic %s", req.Topic)
   101  		return nil
   102  	case err := <-errChan:
   103  		logger.Debugf("Subscription error for topic %s: %v", req.Topic, err)
   104  		return err
   105  	}
   106  }