github.com/wfusion/gofusion@v1.1.14/common/infra/watermill/message/router.go (about)

     1  package message
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"runtime/debug"
     7  	"sync"
     8  	"time"
     9  
    10  	"github.com/pkg/errors"
    11  
    12  	"github.com/wfusion/gofusion/common/infra/watermill"
    13  	"github.com/wfusion/gofusion/common/infra/watermill/pkg"
    14  	"github.com/wfusion/gofusion/common/utils"
    15  )
    16  
    17  var (
    18  	// ErrOutputInNoPublisherHandler happens when a handler func returned some messages in a no-publisher handler.
    19  	// todo: maybe change the handler func signature in no-publisher handler so that there's no possibility for this
    20  	ErrOutputInNoPublisherHandler = errors.New("returned output messages in a handler without publisher")
    21  	ErrRouterIsAlreadyRunning     = errors.New("router is already running")
    22  )
    23  
    24  // HandlerFunc is function called when message is received.
    25  //
    26  // msg.Ack() is called automatically when HandlerFunc doesn't return error.
    27  // When HandlerFunc returns error, msg.Nack() is called.
    28  // When msg.Ack() was called in handler and HandlerFunc returns error,
    29  // msg.Nack() will be not sent because Ack was already sent.
    30  //
    31  // HandlerFunc's are executed parallel when multiple messages was received
    32  // (because msg.Ack() was sent in HandlerFunc or Subscriber supports multiple consumers).
    33  type HandlerFunc func(msg *Message) ([]*Message, error)
    34  
    35  // NoPublishHandlerFunc is HandlerFunc alternative, which doesn't produce any messages.
    36  type NoPublishHandlerFunc func(msg *Message) error
    37  
    38  // PassthroughHandler is a handler that passes the message unchanged from the subscriber to the publisher.
    39  var PassthroughHandler HandlerFunc = func(msg *Message) ([]*Message, error) {
    40  	return []*Message{msg}, nil
    41  }
    42  
    43  // HandlerMiddleware allows us to write something like decorators to HandlerFunc.
    44  // It can execute something before handler (for example: modify consumed message)
    45  // or after (modify produced messages, ack/nack on consumed message, handle errors, logging, etc.).
    46  //
    47  // It can be attached to the router by using `AddMiddleware` method.
    48  //
    49  // Example:
    50  //
    51  //	func ExampleMiddleware(h message.HandlerFunc) message.HandlerFunc {
    52  //		return func(message *message.Message) ([]*message.Message, error) {
    53  //			fmt.Println("executed before handler")
    54  //			producedMessages, err := h(message)
    55  //			fmt.Println("executed after handler")
    56  //
    57  //			return producedMessages, err
    58  //		}
    59  //	}
    60  type HandlerMiddleware func(h HandlerFunc) HandlerFunc
    61  
    62  // RouterPlugin is function which is executed on Router start.
    63  type RouterPlugin func(*Router) error
    64  
    65  // PublisherDecorator wraps the underlying Publisher, adding some functionality.
    66  type PublisherDecorator func(pub Publisher) (Publisher, error)
    67  
    68  // SubscriberDecorator wraps the underlying Subscriber, adding some functionality.
    69  type SubscriberDecorator func(sub Subscriber) (Subscriber, error)
    70  
    71  // RouterConfig holds the Router's configuration options.
    72  type RouterConfig struct {
    73  	// CloseTimeout determines how long router should work for handlers when closing.
    74  	CloseTimeout time.Duration
    75  }
    76  
    77  func (c *RouterConfig) setDefaults() {
    78  	if c.CloseTimeout == 0 {
    79  		c.CloseTimeout = time.Second * 30
    80  	}
    81  }
    82  
    83  // Validate returns Router configuration error, if any.
    84  func (c RouterConfig) Validate() error {
    85  	return nil
    86  }
    87  
    88  // NewRouter creates a new Router with given configuration.
    89  func NewRouter(config RouterConfig, logger watermill.LoggerAdapter) (*Router, error) {
    90  	config.setDefaults()
    91  	if err := config.Validate(); err != nil {
    92  		return nil, errors.Wrap(err, "invalid config")
    93  	}
    94  
    95  	if logger == nil {
    96  		logger = watermill.NopLogger{}
    97  	}
    98  
    99  	return &Router{
   100  		config: config,
   101  
   102  		handlers: map[string]*handler{},
   103  
   104  		handlersWg: &sync.WaitGroup{},
   105  
   106  		runningHandlersWg: &sync.WaitGroup{},
   107  
   108  		handlerAdded: make(chan struct{}),
   109  
   110  		handlersLock: &sync.RWMutex{},
   111  
   112  		ClosingInProgressCh: make(chan struct{}),
   113  		ClosedCh:            make(chan struct{}),
   114  
   115  		logger: logger,
   116  
   117  		running: make(chan struct{}),
   118  	}, nil
   119  }
   120  
   121  type middleware struct {
   122  	Handler       HandlerMiddleware
   123  	HandlerName   string
   124  	IsRouterLevel bool
   125  }
   126  
   127  // Router is responsible for handling messages from subscribers using provided handler functions.
   128  //
   129  // If the handler function returns a message, the message is published with the publisher.
   130  // You can use middlewares to wrap handlers with common logic like logging, instrumentation, etc.
   131  type Router struct {
   132  	config RouterConfig
   133  
   134  	middlewares []middleware
   135  
   136  	plugins []RouterPlugin
   137  
   138  	handlers     map[string]*handler
   139  	handlersLock *sync.RWMutex
   140  
   141  	handlersWg *sync.WaitGroup
   142  
   143  	runningHandlersWg *sync.WaitGroup
   144  
   145  	handlerAdded chan struct{}
   146  
   147  	ClosingInProgressCh chan struct{}
   148  	ClosedCh            chan struct{}
   149  	closed              bool
   150  	closedLock          sync.Mutex
   151  
   152  	logger watermill.LoggerAdapter
   153  
   154  	publisherDecorators  []PublisherDecorator
   155  	subscriberDecorators []SubscriberDecorator
   156  
   157  	isRunning bool
   158  	running   chan struct{}
   159  }
   160  
   161  // Logger returns the Router's logger.
   162  func (r *Router) Logger() watermill.LoggerAdapter {
   163  	return r.logger
   164  }
   165  
   166  // AddMiddleware adds a new middleware to the router.
   167  //
   168  // The order of middleware matters. Middleware added at the beginning is executed first.
   169  func (r *Router) AddMiddleware(m ...HandlerMiddleware) {
   170  	r.logger.Debug("[Common] watermill adding middleware",
   171  		watermill.LogFields{"count": fmt.Sprintf("%d", len(m))})
   172  
   173  	r.addRouterLevelMiddleware(m...)
   174  }
   175  
   176  func (r *Router) addRouterLevelMiddleware(m ...HandlerMiddleware) {
   177  	for _, handlerMiddleware := range m {
   178  		middleware := middleware{
   179  			Handler:       handlerMiddleware,
   180  			HandlerName:   "",
   181  			IsRouterLevel: true,
   182  		}
   183  		r.middlewares = append(r.middlewares, middleware)
   184  	}
   185  }
   186  
   187  func (r *Router) addHandlerLevelMiddleware(handlerName string, m ...HandlerMiddleware) {
   188  	for _, handlerMiddleware := range m {
   189  		middleware := middleware{
   190  			Handler:       handlerMiddleware,
   191  			HandlerName:   handlerName,
   192  			IsRouterLevel: false,
   193  		}
   194  		r.middlewares = append(r.middlewares, middleware)
   195  	}
   196  }
   197  
   198  // AddPlugin adds a new plugin to the router.
   199  // Plugins are executed during startup of the router.
   200  //
   201  // A plugin can, for example, close the router after SIGINT or SIGTERM is sent to the process (SignalsHandler plugin).
   202  func (r *Router) AddPlugin(p ...RouterPlugin) {
   203  	r.logger.Debug("Adding plugins", watermill.LogFields{"count": fmt.Sprintf("%d", len(p))})
   204  
   205  	r.plugins = append(r.plugins, p...)
   206  }
   207  
   208  // AddPublisherDecorators wraps the router's Publisher.
   209  // The first decorator is the innermost, i.e. calls the original publisher.
   210  func (r *Router) AddPublisherDecorators(dec ...PublisherDecorator) {
   211  	r.logger.Debug("Adding publisher decorators", watermill.LogFields{"count": fmt.Sprintf("%d", len(dec))})
   212  
   213  	r.publisherDecorators = append(r.publisherDecorators, dec...)
   214  }
   215  
   216  // AddSubscriberDecorators wraps the router's Subscriber.
   217  // The first decorator is the innermost, i.e. calls the original subscriber.
   218  func (r *Router) AddSubscriberDecorators(dec ...SubscriberDecorator) {
   219  	r.logger.Debug("Adding subscriber decorators", watermill.LogFields{"count": fmt.Sprintf("%d", len(dec))})
   220  
   221  	r.subscriberDecorators = append(r.subscriberDecorators, dec...)
   222  }
   223  
   224  // Handlers returns all registered handlers.
   225  func (r *Router) Handlers() map[string]HandlerFunc {
   226  	handlers := map[string]HandlerFunc{}
   227  
   228  	for handlerName, handler := range r.handlers {
   229  		handlers[handlerName] = handler.handlerFunc
   230  	}
   231  
   232  	return handlers
   233  }
   234  
   235  // DuplicateHandlerNameError is sent in a panic when you try to add a second handler with the same name.
   236  type DuplicateHandlerNameError struct {
   237  	HandlerName string
   238  }
   239  
   240  func (d DuplicateHandlerNameError) Error() string {
   241  	return fmt.Sprintf("handler with name %s already exists", d.HandlerName)
   242  }
   243  
   244  // AddHandler adds a new handler.
   245  //
   246  // handlerName must be unique. For now, it is used only for debugging.
   247  //
   248  // subscribeTopic is a topic from which handler will receive messages.
   249  //
   250  // publishTopic is a topic to which router will produce messages returned by handlerFunc.
   251  // When handler needs to publish to multiple topics,
   252  // it is recommended to just inject Publisher to Handler or implement middleware
   253  // which will catch messages and publish to topic based on metadata for example.
   254  //
   255  // If handler is added while router is already running, you need to explicitly call RunHandlers().
   256  func (r *Router) AddHandler(
   257  	handlerName string,
   258  	subscribeTopic string,
   259  	subscriber Subscriber,
   260  	publishTopic string,
   261  	publisher Publisher,
   262  	handlerFunc HandlerFunc,
   263  ) *Handler {
   264  	r.logger.Info("[Common] watermill adding handler", watermill.LogFields{
   265  		"handler_name": handlerName,
   266  		"topic":        subscribeTopic,
   267  	})
   268  
   269  	r.handlersLock.Lock()
   270  	defer r.handlersLock.Unlock()
   271  
   272  	if _, ok := r.handlers[handlerName]; ok {
   273  		panic(DuplicateHandlerNameError{handlerName})
   274  	}
   275  
   276  	publisherName, subscriberName := pkg.StructName(publisher), pkg.StructName(subscriber)
   277  
   278  	newHandler := &handler{
   279  		name:   handlerName,
   280  		logger: r.logger,
   281  
   282  		subscriber:     subscriber,
   283  		subscribeTopic: subscribeTopic,
   284  		subscriberName: subscriberName,
   285  
   286  		publisher:     publisher,
   287  		publishTopic:  publishTopic,
   288  		publisherName: publisherName,
   289  
   290  		handlerFunc: handlerFunc,
   291  
   292  		runningHandlersWg: r.runningHandlersWg,
   293  
   294  		messagesCh:     nil,
   295  		routersCloseCh: r.ClosingInProgressCh,
   296  
   297  		startedCh: make(chan struct{}),
   298  	}
   299  
   300  	r.handlersWg.Add(1)
   301  	r.handlers[handlerName] = newHandler
   302  
   303  	select {
   304  	case r.handlerAdded <- struct{}{}:
   305  	default:
   306  		// closeWhenAllHandlersStopped is not always waiting for handlerAdded
   307  	}
   308  
   309  	return &Handler{
   310  		router:  r,
   311  		handler: newHandler,
   312  	}
   313  }
   314  
   315  // AddNoPublisherHandler adds a new handler.
   316  // This handler cannot return messages.
   317  // When message is returned it will occur an error and Nack will be sent.
   318  //
   319  // handlerName must be unique. For now, it is used only for debugging.
   320  //
   321  // subscribeTopic is a topic from which handler will receive messages.
   322  //
   323  // subscriber is Subscriber from which messages will be consumed.
   324  //
   325  // If handler is added while router is already running, you need to explicitly call RunHandlers().
   326  func (r *Router) AddNoPublisherHandler(
   327  	handlerName string,
   328  	subscribeTopic string,
   329  	subscriber Subscriber,
   330  	handlerFunc NoPublishHandlerFunc,
   331  ) *Handler {
   332  	handlerFuncAdapter := func(msg *Message) ([]*Message, error) {
   333  		return nil, handlerFunc(msg)
   334  	}
   335  
   336  	return r.AddHandler(handlerName, subscribeTopic, subscriber, "", disabledPublisher{}, handlerFuncAdapter)
   337  }
   338  
   339  // Run runs all plugins and handlers and starts subscribing to provided topics.
   340  // This call is blocking while the router is running.
   341  //
   342  // When all handlers have stopped (for example, because subscriptions were closed), the router will also stop.
   343  //
   344  // To stop Run() you should call Close() on the router.
   345  //
   346  // ctx will be propagated to all subscribers.
   347  //
   348  // When all handlers are stopped (for example: because of closed connection), Run() will be also stopped.
   349  func (r *Router) Run(ctx context.Context) (err error) {
   350  	if r.isRunning {
   351  		return ErrRouterIsAlreadyRunning
   352  	}
   353  	r.isRunning = true
   354  
   355  	ctx, cancel := context.WithCancel(ctx)
   356  	defer cancel()
   357  
   358  	r.logger.Debug("[Common] watermill loading plugins", nil)
   359  	for _, plugin := range r.plugins {
   360  		if err := plugin(r); err != nil {
   361  			return errors.Wrapf(err, "cannot initialize plugin %v", plugin)
   362  		}
   363  	}
   364  
   365  	if err := r.RunHandlers(ctx); err != nil {
   366  		return err
   367  	}
   368  
   369  	close(r.running)
   370  
   371  	go r.closeWhenAllHandlersStopped(ctx)
   372  
   373  	<-r.ClosingInProgressCh
   374  	cancel()
   375  
   376  	r.logger.Info("[Common] watermill waiting for messages", watermill.LogFields{
   377  		"timeout": r.config.CloseTimeout,
   378  	})
   379  
   380  	<-r.ClosedCh
   381  
   382  	r.logger.Info("[Common] watermill all messages processed", nil)
   383  
   384  	return nil
   385  }
   386  
   387  // RunHandlers runs all handlers that were added after Run().
   388  // RunHandlers is idempotent, so can be called multiple times safely.
   389  func (r *Router) RunHandlers(ctx context.Context) error {
   390  	if !r.isRunning {
   391  		return errors.New("you can't call RunHandlers on non-running router")
   392  	}
   393  
   394  	r.handlersLock.Lock()
   395  	defer r.handlersLock.Unlock()
   396  
   397  	r.logger.Info("[Common] watermill running router handlers", watermill.LogFields{"count": len(r.handlers)})
   398  
   399  	for name, h := range r.handlers {
   400  		name := name
   401  		h := h
   402  
   403  		if h.started {
   404  			continue
   405  		}
   406  
   407  		if err := r.decorateHandlerPublisher(h); err != nil {
   408  			return errors.Wrapf(err, "could not decorate publisher of handler %s", name)
   409  		}
   410  		if err := r.decorateHandlerSubscriber(h); err != nil {
   411  			return errors.Wrapf(err, "could not decorate subscriber of handler %s", name)
   412  		}
   413  
   414  		r.logger.Debug("[Common] watermill subscribing to topic", watermill.LogFields{
   415  			"subscriber_name": h.name,
   416  			"topic":           h.subscribeTopic,
   417  		})
   418  
   419  		ctx, cancel := context.WithCancel(ctx)
   420  
   421  		messages, err := h.subscriber.Subscribe(ctx, h.subscribeTopic)
   422  		if err != nil {
   423  			cancel()
   424  			return errors.Wrapf(err, "cannot subscribe topic %s", h.subscribeTopic)
   425  		}
   426  
   427  		h.messagesCh = messages
   428  		h.started = true
   429  		close(h.startedCh)
   430  
   431  		h.stopFn = cancel
   432  		h.stopped = make(chan struct{})
   433  
   434  		go func() {
   435  			defer cancel()
   436  
   437  			h.run(ctx, r.middlewares)
   438  
   439  			r.handlersWg.Done()
   440  			r.logger.Info("[Common] watermill subscriber stopped", watermill.LogFields{
   441  				"subscriber_name": h.name,
   442  				"topic":           h.subscribeTopic,
   443  			})
   444  
   445  			r.handlersLock.Lock()
   446  			delete(r.handlers, name)
   447  			r.handlersLock.Unlock()
   448  		}()
   449  	}
   450  	return nil
   451  }
   452  
   453  // closeWhenAllHandlersStopped closed router, when all handlers has stopped,
   454  // because for example all subscriptions are closed.
   455  func (r *Router) closeWhenAllHandlersStopped(ctx context.Context) {
   456  	r.handlersLock.RLock()
   457  	hasHandlers := len(r.handlers) == 0
   458  	r.handlersLock.RUnlock()
   459  
   460  	if hasHandlers {
   461  		// in that situation router will be closed immediately (even if they are no routers)
   462  		// let's wait for
   463  		select {
   464  		case <-r.handlerAdded:
   465  			// it should be some handler to track
   466  		case <-r.ClosedCh:
   467  			// let's avoid goroutine leak
   468  			return
   469  		}
   470  	}
   471  
   472  	r.handlersWg.Wait()
   473  	if r.IsClosed() {
   474  		// already closed
   475  		return
   476  	}
   477  
   478  	// Only log an error if the context was not canceled, but handlers were stopped.
   479  	select {
   480  	case <-ctx.Done():
   481  	default:
   482  		r.logger.Error("[Common] watermill all handlers stopped, closing router",
   483  			errors.New("all router handlers stopped"), nil)
   484  	}
   485  
   486  	if err := r.Close(); err != nil {
   487  		r.logger.Error("[Common] watermill cannot close router", err, nil)
   488  	}
   489  }
   490  
   491  // Running is closed when router is running.
   492  // In other words: you can wait till router is running using
   493  //
   494  //	fmt.Println("Starting router")
   495  //	go r.Run(ctx)
   496  //	<- r.Running()
   497  //	fmt.Println("Router is running")
   498  //
   499  // Warning: for historical reasons, this channel is not aware of router closing -
   500  // the channel will be closed if the router has been running and closed.
   501  func (r *Router) Running() chan struct{} {
   502  	return r.running
   503  }
   504  
   505  // IsRunning returns true when router is running.
   506  //
   507  // Warning: for historical reasons, this method is not aware of router closing.
   508  // If you want to know if the router was closed, use IsClosed.
   509  func (r *Router) IsRunning() bool {
   510  	select {
   511  	case <-r.running:
   512  		return true
   513  	default:
   514  		return false
   515  	}
   516  }
   517  
   518  // Close gracefully closes the router with a timeout provided in the configuration.
   519  func (r *Router) Close() error {
   520  	r.closedLock.Lock()
   521  	defer r.closedLock.Unlock()
   522  
   523  	r.handlersLock.Lock()
   524  	defer r.handlersLock.Unlock()
   525  
   526  	if r.closed {
   527  		return nil
   528  	}
   529  	r.closed = true
   530  
   531  	r.logger.Info("[Common] watermill closing router", nil)
   532  	defer r.logger.Info("[Common] watermill router closed", nil)
   533  
   534  	close(r.ClosingInProgressCh)
   535  	defer close(r.ClosedCh)
   536  
   537  	timeouted := r.waitForHandlers()
   538  	if timeouted {
   539  		return errors.New("router close timeout")
   540  	}
   541  
   542  	return nil
   543  }
   544  
   545  func (r *Router) waitForHandlers() bool {
   546  	var waitGroup sync.WaitGroup
   547  	waitGroup.Add(1)
   548  	go func() {
   549  		defer waitGroup.Done()
   550  		r.handlersWg.Wait()
   551  	}()
   552  	waitGroup.Add(1)
   553  	go func() {
   554  		defer waitGroup.Done()
   555  
   556  		r.runningHandlersWg.Wait()
   557  	}()
   558  	return utils.Timeout(r.config.CloseTimeout, utils.TimeoutWg(&waitGroup))
   559  }
   560  
   561  func (r *Router) IsClosed() bool {
   562  	r.closedLock.Lock()
   563  	defer r.closedLock.Unlock()
   564  
   565  	return r.closed
   566  }
   567  
   568  type handler struct {
   569  	name   string
   570  	logger watermill.LoggerAdapter
   571  
   572  	subscriber     Subscriber
   573  	subscribeTopic string
   574  	subscriberName string
   575  
   576  	publisher     Publisher
   577  	publishTopic  string
   578  	publisherName string
   579  
   580  	handlerFunc HandlerFunc
   581  
   582  	runningHandlersWg *sync.WaitGroup
   583  
   584  	messagesCh <-chan *Message
   585  
   586  	started   bool
   587  	startedCh chan struct{}
   588  
   589  	stopFn         context.CancelFunc
   590  	stopped        chan struct{}
   591  	routersCloseCh chan struct{}
   592  }
   593  
   594  func (h *handler) run(ctx context.Context, middlewares []middleware) {
   595  	h.logger.Info("[Common] watermill starting handler", watermill.LogFields{
   596  		"subscriber_name": h.name,
   597  		"topic":           h.subscribeTopic,
   598  	})
   599  
   600  	middlewareHandler := h.handlerFunc
   601  	// first added middlewares should be executed first (so should be at the top of call stack)
   602  	for i := len(middlewares) - 1; i >= 0; i-- {
   603  		currentMiddleware := middlewares[i]
   604  		isValidHandlerLevelMiddleware := currentMiddleware.HandlerName == h.name
   605  		if currentMiddleware.IsRouterLevel || isValidHandlerLevelMiddleware {
   606  			middlewareHandler = currentMiddleware.Handler(middlewareHandler)
   607  		}
   608  	}
   609  
   610  	go h.handleClose(ctx)
   611  
   612  	for msg := range h.messagesCh {
   613  		h.runningHandlersWg.Add(1)
   614  		go h.handleMessage(msg, middlewareHandler)
   615  	}
   616  
   617  	if h.publisher != nil {
   618  		h.logger.Debug("[Common] watermill waiting for publisher to close", nil)
   619  		if err := h.publisher.Close(); err != nil {
   620  			h.logger.Error("[Common] watermill failed to close publisher", err, nil)
   621  		}
   622  		h.logger.Debug("[Common] watermill publisher closed", nil)
   623  	}
   624  
   625  	h.logger.Debug("[Common] watermill router handler stopped", nil)
   626  	close(h.stopped)
   627  }
   628  
   629  // Handler handles Messages.
   630  type Handler struct {
   631  	router  *Router
   632  	handler *handler
   633  }
   634  
   635  // AddMiddleware adds new middleware to the specified handler in the router.
   636  //
   637  // The order of middleware matters. Middleware added at the beginning is executed first.
   638  func (h *Handler) AddMiddleware(m ...HandlerMiddleware) {
   639  	handler := h.handler
   640  	handler.logger.Debug("[Common] watermill adding middleware to handler", watermill.LogFields{
   641  		"count":       fmt.Sprintf("%d", len(m)),
   642  		"handlerName": handler.name,
   643  	})
   644  
   645  	h.router.addHandlerLevelMiddleware(handler.name, m...)
   646  }
   647  
   648  // Started returns channel which is stopped when handler is running.
   649  func (h *Handler) Started() chan struct{} {
   650  	return h.handler.startedCh
   651  }
   652  
   653  // Stop stops the handler.
   654  // Stop is asynchronous.
   655  // You can check if handler was stopped with Stopped() function.
   656  func (h *Handler) Stop() {
   657  	if !h.handler.started {
   658  		panic("handler is not started")
   659  	}
   660  
   661  	h.handler.stopFn()
   662  }
   663  
   664  // Stopped returns channel which is stopped when handler did stop.
   665  func (h *Handler) Stopped() chan struct{} {
   666  	return h.handler.stopped
   667  }
   668  
   669  // decorateHandlerPublisher applies the decorator chain to handler's publisher.
   670  // They are applied in reverse order, so that the later decorators use the result of former ones.
   671  func (r *Router) decorateHandlerPublisher(h *handler) error {
   672  	var err error
   673  	pub := h.publisher
   674  	for i := len(r.publisherDecorators) - 1; i >= 0; i-- {
   675  		decorator := r.publisherDecorators[i]
   676  		pub, err = decorator(pub)
   677  		if err != nil {
   678  			return errors.Wrap(err, "could not apply publisher decorator")
   679  		}
   680  	}
   681  	r.handlers[h.name].publisher = pub
   682  	return nil
   683  }
   684  
   685  // decorateHandlerSubscriber applies the decorator chain to handler's subscriber.
   686  // They are applied in regular order, so that the later decorators use the result of former ones.
   687  func (r *Router) decorateHandlerSubscriber(h *handler) error {
   688  	var err error
   689  	sub := h.subscriber
   690  
   691  	// add values to message context to subscriber
   692  	// it goes before other decorators, so that they may take advantage of these values
   693  	messageTransform := func(msg *Message) {
   694  		if msg != nil {
   695  			h.addHandlerContext(msg)
   696  		}
   697  	}
   698  	sub, err = MessageTransformSubscriberDecorator(messageTransform)(sub)
   699  	if err != nil {
   700  		return errors.Wrapf(err, "cannot wrap subscriber with context decorator")
   701  	}
   702  
   703  	for _, decorator := range r.subscriberDecorators {
   704  		sub, err = decorator(sub)
   705  		if err != nil {
   706  			return errors.Wrap(err, "could not apply subscriber decorator")
   707  		}
   708  	}
   709  	r.handlers[h.name].subscriber = sub
   710  	return nil
   711  }
   712  
   713  // addHandlerContext enriches the contex with values that are relevant within this handler's context.
   714  func (h *handler) addHandlerContext(messages ...*Message) {
   715  	for i, msg := range messages {
   716  		ctx := msg.Context()
   717  
   718  		if h.name != "" {
   719  			ctx = context.WithValue(ctx, handlerNameKey, h.name)
   720  		}
   721  		if h.publisherName != "" {
   722  			ctx = context.WithValue(ctx, publisherNameKey, h.publisherName)
   723  		}
   724  		if h.subscriberName != "" {
   725  			ctx = context.WithValue(ctx, subscriberNameKey, h.subscriberName)
   726  		}
   727  		if h.subscribeTopic != "" {
   728  			ctx = context.WithValue(ctx, subscribeTopicKey, h.subscribeTopic)
   729  		}
   730  		if h.publishTopic != "" {
   731  			ctx = context.WithValue(ctx, publishTopicKey, h.publishTopic)
   732  		}
   733  		messages[i].SetContext(ctx)
   734  	}
   735  }
   736  
   737  func (h *handler) handleClose(ctx context.Context) {
   738  	select {
   739  	case <-h.routersCloseCh:
   740  		// for backward compatibility we are closing subscriber
   741  		h.logger.Debug("[Common] watermill waiting for subscriber to close", nil)
   742  		if err := h.subscriber.Close(); err != nil {
   743  			h.logger.Error("[Common] watermill failed to close subscriber", err, nil)
   744  		}
   745  		h.logger.Debug("[Common] watermill subscriber closed", nil)
   746  	case <-ctx.Done():
   747  		// we are closing subscriber just when entire router is closed
   748  	}
   749  	h.stopFn()
   750  }
   751  
   752  func (h *handler) handleMessage(msg *Message, handler HandlerFunc) {
   753  	defer h.runningHandlersWg.Done()
   754  	msgFields := watermill.LogFields{"message_uuid": msg.UUID}
   755  
   756  	defer func() {
   757  		if recovered := recover(); recovered != nil {
   758  			h.logger.Error(
   759  				"[Common] watermill panic recovered in handler. Stack: "+string(debug.Stack()),
   760  				errors.Errorf("%s", recovered),
   761  				msgFields,
   762  			)
   763  			msg.Nack()
   764  		}
   765  	}()
   766  
   767  	h.logger.Trace("[Common] watermill received message", msgFields)
   768  
   769  	producedMessages, err := handler(msg)
   770  	if err != nil {
   771  		h.logger.Error("[Common] watermill handler returned error", err, nil)
   772  		msg.Nack()
   773  		return
   774  	}
   775  
   776  	// ack & nack by business for non-router calling
   777  	disableAck := false
   778  	if len(producedMessages) > 0 {
   779  		for i, msg := range producedMessages {
   780  			if _, disableAck = msg.Metadata[watermill.MessageRouterAck]; disableAck {
   781  				producedMessages = append(producedMessages[0:i], producedMessages[i+1:]...)
   782  			}
   783  		}
   784  	}
   785  
   786  	h.addHandlerContext(producedMessages...)
   787  
   788  	if err := h.publishProducedMessages(msg.Context(), producedMessages, msgFields); err != nil {
   789  		h.logger.Error("[Common] watermill publishing produced messages failed", err, nil)
   790  		if !disableAck {
   791  			msg.Nack()
   792  		} else {
   793  			h.logger.Trace("[Common] watermill message should be nack by business", msgFields)
   794  		}
   795  		return
   796  	}
   797  	if !disableAck {
   798  		msg.Ack()
   799  		h.logger.Trace("[Common] watermill message acked", msgFields)
   800  	} else {
   801  		h.logger.Trace("[Common] watermill message should be acked by business", msgFields)
   802  	}
   803  }
   804  
   805  func (h *handler) publishProducedMessages(ctx context.Context,
   806  	producedMessages Messages, msgFields watermill.LogFields) error {
   807  	if len(producedMessages) == 0 {
   808  		return nil
   809  	}
   810  
   811  	if h.publisher == nil {
   812  		return ErrOutputInNoPublisherHandler
   813  	}
   814  
   815  	h.logger.Trace("Sending produced messages", msgFields.Add(watermill.LogFields{
   816  		"produced_messages_count": len(producedMessages),
   817  		"publish_topic":           h.publishTopic,
   818  	}))
   819  
   820  	for _, msg := range producedMessages {
   821  		if err := h.publisher.Publish(ctx, h.publishTopic, msg); err != nil {
   822  			// todo - how to deal with it better/transactional/retry?
   823  			h.logger.Error("Cannot publish message", err, msgFields.Add(watermill.LogFields{
   824  				"not_sent_message": fmt.Sprintf("%#v", producedMessages),
   825  			}))
   826  
   827  			return err
   828  		}
   829  	}
   830  
   831  	return nil
   832  }
   833  
   834  type disabledPublisher struct{}
   835  
   836  func (disabledPublisher) Publish(ctx context.Context, topic string, messages ...*Message) error {
   837  	return ErrOutputInNoPublisherHandler
   838  }
   839  
   840  func (disabledPublisher) Close() error {
   841  	return nil
   842  }