package tracker import ( "errors" "sync" ) var ErrMappingNotFound = errors.New("tracker mapping not found") type Mapping struct { MessageID string SequenceID uint32 GatewayMessageID string } type Tracker struct { mu sync.RWMutex byMessage map[string]Mapping bySeq map[uint32]string byGateway map[string]string } func New() *Tracker { return &Tracker{ byMessage: make(map[string]Mapping), bySeq: make(map[uint32]string), byGateway: make(map[string]string), } } func (t *Tracker) TrackSubmit(messageID string, sequenceID uint32) Mapping { t.mu.Lock() defer t.mu.Unlock() mapping := t.byMessage[messageID] mapping.MessageID = messageID mapping.SequenceID = sequenceID t.byMessage[messageID] = mapping t.bySeq[sequenceID] = messageID return mapping } func (t *Tracker) TrackSubmitResp(sequenceID uint32, gatewayMessageID string) (Mapping, error) { t.mu.Lock() defer t.mu.Unlock() messageID, ok := t.bySeq[sequenceID] if !ok { return Mapping{}, ErrMappingNotFound } mapping := t.byMessage[messageID] mapping.GatewayMessageID = gatewayMessageID t.byMessage[messageID] = mapping t.byGateway[gatewayMessageID] = messageID return mapping, nil } func (t *Tracker) ByGatewayMessageID(gatewayMessageID string) (Mapping, error) { t.mu.RLock() defer t.mu.RUnlock() messageID, ok := t.byGateway[gatewayMessageID] if !ok { return Mapping{}, ErrMappingNotFound } return t.byMessage[messageID], nil } func (t *Tracker) ByMessageID(messageID string) (Mapping, error) { t.mu.RLock() defer t.mu.RUnlock() mapping, ok := t.byMessage[messageID] if !ok { return Mapping{}, ErrMappingNotFound } return mapping, nil }