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 }