✨ Update dependencies, enhance NATS consumer configuration, and improve error handling in message processing. Introduce telemetry support with OpenTelemetry for tracing and metrics. Refactor README to include new configuration options and update tests for improved coverage of error scenarios.
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestMapper(t *testing.T) {
|
||||
RegisterFailHandler(Fail)
|
||||
RunSpecs(t, "Adapter Mapper Suite")
|
||||
}
|
||||
@@ -43,6 +43,11 @@ func (m *TelegramMapper) ToDBRow(msg *domain.ParsedMessage) ([]interface{}, erro
|
||||
// SecondaryAddresses is already a string, so we can use it directly
|
||||
secondaryAddresses := msg.SecondaryAddresses
|
||||
|
||||
status := msg.Status
|
||||
if status == "" {
|
||||
status = domain.MessageStatusUnknown
|
||||
}
|
||||
|
||||
return []interface{}{
|
||||
msgUUID, // uuid
|
||||
msg.MessageID, // message_id
|
||||
@@ -55,6 +60,8 @@ func (m *TelegramMapper) ToDBRow(msg *domain.ParsedMessage) ([]interface{}, erro
|
||||
msg.Category, // category
|
||||
msg.Content, // content (TEXT, original message)
|
||||
bodyDataJSON, // body_data (JSONB)
|
||||
string(status), // status
|
||||
msg.ErrorReason, // error_reason
|
||||
msg.ReceivedAt, // received_at
|
||||
msg.ParsedAt, // parsed_at
|
||||
msg.DispatchedAt, // dispatched_at
|
||||
@@ -64,7 +71,7 @@ func (m *TelegramMapper) ToDBRow(msg *domain.ParsedMessage) ([]interface{}, erro
|
||||
|
||||
// FromDBRow converts a database row to a domain.ParsedMessage
|
||||
func (m *TelegramMapper) FromDBRow(row []interface{}) (*domain.ParsedMessage, error) {
|
||||
const expectedColumns = 15
|
||||
const expectedColumns = 17
|
||||
if len(row) < expectedColumns {
|
||||
return nil, fmt.Errorf("expected %d columns, got %d", expectedColumns, len(row))
|
||||
}
|
||||
@@ -94,6 +101,19 @@ func (m *TelegramMapper) FromDBRow(row []interface{}) (*domain.ParsedMessage, er
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
toBool := func(v interface{}) bool {
|
||||
switch val := v.(type) {
|
||||
case bool:
|
||||
return val
|
||||
case *bool:
|
||||
return val != nil && *val
|
||||
case int64:
|
||||
return val != 0
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var bodyData interface{}
|
||||
if raw := row[10]; raw != nil {
|
||||
switch val := raw.(type) {
|
||||
@@ -108,7 +128,10 @@ func (m *TelegramMapper) FromDBRow(row []interface{}) (*domain.ParsedMessage, er
|
||||
}
|
||||
}
|
||||
|
||||
needDispatch, _ := row[14].(bool)
|
||||
status := domain.MessageStatusUnknown
|
||||
if rawStatus := toString(row[11]); rawStatus != "" {
|
||||
status = domain.MessageStatus(rawStatus)
|
||||
}
|
||||
|
||||
return &domain.ParsedMessage{
|
||||
Uuid: msgUUID.String(),
|
||||
@@ -122,9 +145,11 @@ func (m *TelegramMapper) FromDBRow(row []interface{}) (*domain.ParsedMessage, er
|
||||
Category: toString(row[8]),
|
||||
Content: toString(row[9]),
|
||||
BodyData: bodyData,
|
||||
ReceivedAt: parseTime(row[11]),
|
||||
ParsedAt: parseTime(row[12]),
|
||||
DispatchedAt: parseTime(row[13]),
|
||||
NeedDispatch: needDispatch,
|
||||
Status: status,
|
||||
ErrorReason: toString(row[12]),
|
||||
ReceivedAt: parseTime(row[13]),
|
||||
ParsedAt: parseTime(row[14]),
|
||||
DispatchedAt: parseTime(row[15]),
|
||||
NeedDispatch: toBool(row[16]),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1,71 +1,68 @@
|
||||
package mapper
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"caatsm/internal/domain"
|
||||
|
||||
"github.com/google/uuid"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestTelegramMapper_ToDBRow_GeneratesUUIDWhenEmpty(t *testing.T) {
|
||||
mapper := NewTelegramMapper()
|
||||
msg := &domain.ParsedMessage{}
|
||||
var _ = Describe("TelegramMapper", func() {
|
||||
var mapper *TelegramMapper
|
||||
|
||||
row, err := mapper.ToDBRow(msg)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
BeforeEach(func() {
|
||||
mapper = NewTelegramMapper()
|
||||
})
|
||||
|
||||
value, ok := row[0].(uuid.UUID)
|
||||
if !ok {
|
||||
t.Fatalf("expected first column to be uuid.UUID, got %T", row[0])
|
||||
}
|
||||
if value == uuid.Nil {
|
||||
t.Fatalf("expected generated uuid to be non-nil")
|
||||
}
|
||||
}
|
||||
Describe("ToDBRow", func() {
|
||||
It("generates a UUID when missing", func() {
|
||||
msg := &domain.ParsedMessage{}
|
||||
|
||||
func TestTelegramMapper_FromDBRow_RoundTrip(t *testing.T) {
|
||||
mapper := NewTelegramMapper()
|
||||
now := time.Now().UTC()
|
||||
row, err := mapper.ToDBRow(msg)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
original := &domain.ParsedMessage{
|
||||
Uuid: uuid.NewString(),
|
||||
MessageID: "TMQ1324",
|
||||
DateTime: "150631",
|
||||
PriorityIndicator: "FF",
|
||||
PrimaryAddress: "ZBTJZPZX",
|
||||
SecondaryAddresses: "150630 ZBACZQZX",
|
||||
Originator: "ORIGIN",
|
||||
OriginatorDateTime: "150630",
|
||||
Category: "FPL",
|
||||
Content: "raw telegram",
|
||||
BodyData: map[string]string{"key": "value"},
|
||||
ReceivedAt: now,
|
||||
ParsedAt: now,
|
||||
DispatchedAt: now,
|
||||
NeedDispatch: true,
|
||||
}
|
||||
value, ok := row[0].(uuid.UUID)
|
||||
Expect(ok).To(BeTrue())
|
||||
Expect(value).NotTo(Equal(uuid.Nil))
|
||||
})
|
||||
})
|
||||
|
||||
row, err := mapper.ToDBRow(original)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
Describe("FromDBRow", func() {
|
||||
It("round-trips telegram data", func() {
|
||||
now := time.Now().UTC()
|
||||
original := &domain.ParsedMessage{
|
||||
Uuid: uuid.NewString(),
|
||||
MessageID: "TMQ1324",
|
||||
DateTime: "150631",
|
||||
PriorityIndicator: "FF",
|
||||
PrimaryAddress: "ZBTJZPZX",
|
||||
SecondaryAddresses: "150630 ZBACZQZX",
|
||||
Originator: "ORIGIN",
|
||||
OriginatorDateTime: "150630",
|
||||
Category: "FPL",
|
||||
Content: "raw telegram",
|
||||
BodyData: map[string]string{"key": "value"},
|
||||
ReceivedAt: now,
|
||||
ParsedAt: now,
|
||||
DispatchedAt: now,
|
||||
NeedDispatch: true,
|
||||
Status: domain.MessageStatusParsed,
|
||||
}
|
||||
|
||||
roundTrip, err := mapper.FromDBRow(row)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error reading row: %v", err)
|
||||
}
|
||||
row, err := mapper.ToDBRow(original)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(row).To(HaveLen(17))
|
||||
|
||||
if roundTrip.Uuid != original.Uuid {
|
||||
t.Fatalf("expected uuid %s, got %s", original.Uuid, roundTrip.Uuid)
|
||||
}
|
||||
if roundTrip.MessageID != original.MessageID {
|
||||
t.Fatalf("expected message_id %s, got %s", original.MessageID, roundTrip.MessageID)
|
||||
}
|
||||
if roundTrip.NeedDispatch != original.NeedDispatch {
|
||||
t.Fatalf("expected need_dispatch %v, got %v", original.NeedDispatch, roundTrip.NeedDispatch)
|
||||
}
|
||||
}
|
||||
roundTrip, err := mapper.FromDBRow(row)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
Expect(roundTrip.Uuid).To(Equal(original.Uuid))
|
||||
Expect(roundTrip.MessageID).To(Equal(original.MessageID))
|
||||
Expect(roundTrip.NeedDispatch).To(Equal(original.NeedDispatch))
|
||||
Expect(roundTrip.Status).To(Equal(original.Status))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user