github.com/s7techlab/cckit@v0.10.5/state/mapping/event_mapping.go (about)

     1  package mapping
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"strings"
     7  
     8  	"github.com/golang/protobuf/proto"
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/s7techlab/cckit/state"
    12  )
    13  
    14  var (
    15  	ErrEventNameNotFound = errors.New(`event name not found`)
    16  )
    17  
    18  type (
    19  	Namer func(entity interface{}) string
    20  
    21  	EventMapping struct {
    22  		schema interface{}
    23  		name   string
    24  	}
    25  
    26  	EventMappings map[string]*EventMapping
    27  
    28  	EventMapped interface {
    29  		state.NameValue
    30  	}
    31  
    32  	EventMappers interface {
    33  		Exists(schema interface{}) (exists bool)
    34  		Map(schema interface{}) (keyValue state.KeyValue, err error)
    35  		Get(schema interface{}) (eventMapper EventMapper, err error)
    36  	}
    37  
    38  	EventMapper interface {
    39  		Schema() interface{}
    40  		Name(instance interface{}) (string, error)
    41  	}
    42  
    43  	Event struct {
    44  		Name    string
    45  		Payload interface{}
    46  	}
    47  
    48  	EventMappingOpt func(*EventMapping)
    49  
    50  	EventResolver interface {
    51  		Resolve(eventName string, payload []byte) (event interface{}, err error)
    52  	}
    53  )
    54  
    55  func (emm EventMappings) Add(schema interface{}, opts ...EventMappingOpt) EventMappings {
    56  	em := &EventMapping{
    57  		schema: schema,
    58  	}
    59  
    60  	for _, opt := range opts {
    61  		opt(em)
    62  	}
    63  
    64  	applyEventMappingDefaults(em)
    65  	emm[mapKey(schema)] = em
    66  	return emm
    67  }
    68  
    69  func applyEventMappingDefaults(em *EventMapping) {
    70  	// default namespace based on type names
    71  	if len(em.name) == 0 {
    72  		em.name = EventNameForPayload(em.schema)
    73  	}
    74  }
    75  
    76  func (emm EventMappings) Get(entry interface{}) (EventMapper, error) {
    77  	m, ok := emm[mapKey(entry)]
    78  	if !ok {
    79  		return nil, fmt.Errorf(`%s: %s`, ErrEventMappingNotFound, mapKey(entry))
    80  	}
    81  	return m, nil
    82  }
    83  
    84  func (emm EventMappings) Exists(entry interface{}) bool {
    85  	_, err := emm.Get(entry)
    86  	return err == nil
    87  }
    88  
    89  func (emm EventMappings) Map(entry interface{}) (instance *EventInstance, err error) {
    90  	mapping, err := emm.Get(entry)
    91  	if err != nil {
    92  		return nil, errors.Wrap(err, `mapping`)
    93  	}
    94  
    95  	switch entry.(type) {
    96  	case proto.Message:
    97  		return NewEventInstance(entry, mapping, DefaultSerializer)
    98  	default:
    99  		return nil, ErrEntryTypeNotSupported
   100  	}
   101  }
   102  
   103  func (emm EventMappings) Resolve(eventName string, payload []byte) (event interface{}, err error) {
   104  	for _, m := range emm {
   105  		if m.name == eventName {
   106  			return DefaultSerializer.FromBytes(payload, m.Schema())
   107  		}
   108  	}
   109  
   110  	return nil, ErrEventNameNotFound
   111  }
   112  
   113  func (em EventMapping) Schema() interface{} {
   114  	return em.schema
   115  }
   116  
   117  func (em EventMapping) Name(instance interface{}) (string, error) {
   118  	return em.name, nil
   119  }
   120  
   121  func EventNameForPayload(payload interface{}) string {
   122  	t := reflect.TypeOf(payload).String()
   123  	return t[strings.Index(t, `.`)+1:]
   124  }
   125  
   126  func EventFromPayload(payload interface{}) *Event {
   127  	return &Event{
   128  		Name:    EventNameForPayload(payload),
   129  		Payload: payload,
   130  	}
   131  }
   132  
   133  func MergeEventMappings(one EventMappings, more ...EventMappings) EventMappings {
   134  	out := make(EventMappings)
   135  	for k, v := range one {
   136  		out[k] = v
   137  	}
   138  
   139  	for _, m := range more {
   140  		for k, v := range m {
   141  			out[k] = v
   142  		}
   143  	}
   144  	return out
   145  }