2014-11-28 22:16:49 +01:00
package bus
import (
2016-10-03 09:38:03 +02:00
"context"
2018-04-27 13:41:58 +02:00
"errors"
2020-11-17 11:27:45 +01:00
"fmt"
2014-11-28 22:16:49 +01:00
"reflect"
2020-11-27 14:58:45 +01:00
2021-07-15 14:33:38 +02:00
"github.com/grafana/grafana/pkg/infra/log"
2022-01-20 11:10:12 +01:00
"github.com/grafana/grafana/pkg/infra/tracing"
2021-07-15 14:33:38 +02:00
"github.com/grafana/grafana/pkg/setting"
2022-01-20 11:10:12 +01:00
"go.opentelemetry.io/otel/attribute"
2014-11-28 22:16:49 +01:00
)
2019-06-04 22:00:05 +02:00
// HandlerFunc defines a handler function interface.
2014-12-16 16:45:07 +01:00
type HandlerFunc interface { }
2019-06-04 22:00:05 +02:00
// Msg defines a message interface.
2014-12-16 16:45:07 +01:00
type Msg interface { }
2014-11-28 22:16:49 +01:00
2019-06-04 22:00:05 +02:00
// ErrHandlerNotFound defines an error if a handler is not found
2018-04-27 13:41:58 +02:00
var ErrHandlerNotFound = errors . New ( "handler not found" )
2019-06-04 22:00:05 +02:00
// Bus type defines the bus interface structure
2014-12-01 08:56:03 -08:00
type Bus interface {
2022-01-04 09:36:01 +01:00
Publish ( ctx context . Context , msg Msg ) error
AddEventListener ( handler HandlerFunc )
2018-06-05 21:13:53 +02:00
}
2019-06-04 22:00:05 +02:00
// InProcBus defines the bus structure
2014-12-01 08:56:03 -08:00
type InProcBus struct {
2021-11-19 13:56:42 +01:00
logger log . Logger
listeners map [ string ] [ ] HandlerFunc
listenersWithCtx map [ string ] [ ] HandlerFunc
2022-01-20 11:10:12 +01:00
tracer tracing . Tracer
2014-12-01 08:56:03 -08:00
}
2014-11-28 22:16:49 +01:00
2022-01-20 11:10:12 +01:00
func ProvideBus ( tracer tracing . Tracer ) * InProcBus {
globalBus . tracer = tracer
2021-08-25 15:11:22 +02:00
return globalBus
}
2014-12-16 12:04:08 +01:00
// temp stuff, not sure how to handle bus instance, and init yet
var globalBus = New ( )
2019-06-04 22:00:05 +02:00
// New initialize the bus
2021-08-25 15:11:22 +02:00
func New ( ) * InProcBus {
2022-01-20 11:10:12 +01:00
bus := & InProcBus {
2021-11-19 13:56:42 +01:00
logger : log . New ( "bus" ) ,
listeners : make ( map [ string ] [ ] HandlerFunc ) ,
listenersWithCtx : make ( map [ string ] [ ] HandlerFunc ) ,
2021-07-15 14:33:38 +02:00
}
2022-01-20 11:10:12 +01:00
bus . tracer = tracing . InitializeForBus ( )
return bus
2014-11-28 22:16:49 +01:00
}
2021-11-19 13:56:42 +01:00
// PublishCtx function publish a message to the bus listener.
2022-01-04 09:36:01 +01:00
func ( b * InProcBus ) Publish ( ctx context . Context , msg Msg ) error {
2021-11-19 13:56:42 +01:00
var msgName = reflect . TypeOf ( msg ) . Elem ( ) . Name ( )
var params = [ ] reflect . Value { }
if listeners , exists := b . listenersWithCtx [ msgName ] ; exists {
params = append ( params , reflect . ValueOf ( ctx ) )
params = append ( params , reflect . ValueOf ( msg ) )
2021-11-19 14:32:14 +01:00
if err := callListeners ( listeners , params ) ; err != nil {
2021-11-19 13:56:42 +01:00
return err
}
}
if listeners , exists := b . listeners [ msgName ] ; exists {
params = append ( params , reflect . ValueOf ( msg ) )
if setting . Env == setting . Dev {
b . logger . Warn ( "PublishCtx called with message listener registered using AddEventListener and should be changed to use AddEventListenerCtx" , "msgName" , msgName )
}
2021-11-19 14:32:14 +01:00
if err := callListeners ( listeners , params ) ; err != nil {
2021-11-19 13:56:42 +01:00
return err
}
}
2022-01-20 11:10:12 +01:00
_ , span := b . tracer . Start ( ctx , "bus - " + msgName )
defer span . End ( )
2021-11-19 13:56:42 +01:00
2022-01-20 11:10:12 +01:00
span . SetAttributes ( "msg" , msgName , attribute . Key ( "msg" ) . String ( msgName ) )
2021-11-19 13:56:42 +01:00
return nil
}
2021-11-19 14:32:14 +01:00
func callListeners ( listeners [ ] HandlerFunc , params [ ] reflect . Value ) error {
2015-02-03 23:57:42 +08:00
for _ , listenerHandler := range listeners {
2015-01-09 16:36:23 +01:00
ret := reflect . ValueOf ( listenerHandler ) . Call ( params )
2020-11-17 11:27:45 +01:00
e := ret [ 0 ] . Interface ( )
if e != nil {
err , ok := e . ( error )
if ok {
return err
}
return fmt . Errorf ( "expected listener to return an error, got '%T'" , e )
2015-01-09 16:36:23 +01:00
}
}
return nil
}
2022-01-04 09:36:01 +01:00
func ( b * InProcBus ) AddEventListener ( handler HandlerFunc ) {
2021-11-19 13:56:42 +01:00
handlerType := reflect . TypeOf ( handler )
eventName := handlerType . In ( 1 ) . Elem ( ) . Name ( )
_ , exists := b . listenersWithCtx [ eventName ]
if ! exists {
b . listenersWithCtx [ eventName ] = make ( [ ] HandlerFunc , 0 )
}
b . listenersWithCtx [ eventName ] = append ( b . listenersWithCtx [ eventName ] , handler )
}
// AddEventListenerCtx attaches a handler function to the event listener.
// Package level function.
2022-01-04 09:36:01 +01:00
func AddEventListener ( handler HandlerFunc ) {
globalBus . AddEventListener ( handler )
2021-11-19 13:56:42 +01:00
}
2022-01-04 09:36:01 +01:00
func Publish ( ctx context . Context , msg Msg ) error {
return globalBus . Publish ( ctx , msg )
2021-11-19 13:56:42 +01:00
}