Files
sendico/api/edge/callbacks/internal/events/service.go
2026-02-28 10:10:26 +01:00

87 lines
2.4 KiB
Go

package events
import (
"context"
"encoding/json"
"strings"
"time"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/mlogger"
"go.uber.org/zap"
)
type parserService struct {
logger mlogger.Logger
}
// New creates event parser/payload builder service.
func New(logger mlogger.Logger) Service {
if logger == nil {
logger = zap.NewNop()
}
return &parserService{logger: logger.Named("events")}
}
func (s *parserService) Parse(data []byte) (*Envelope, error) {
if len(data) == 0 {
return nil, merrors.InvalidArgument("event payload is empty", "data")
}
var envelope Envelope
if err := json.Unmarshal(data, &envelope); err != nil {
return nil, merrors.InvalidArgumentWrap(err, "event payload is not valid JSON", "data")
}
if strings.TrimSpace(envelope.EventID) == "" {
return nil, merrors.InvalidArgument("event_id is required", "event_id")
}
if strings.TrimSpace(envelope.Type) == "" {
return nil, merrors.InvalidArgument("type is required", "type")
}
if strings.TrimSpace(envelope.ClientID) == "" {
return nil, merrors.InvalidArgument("client_id is required", "client_id")
}
if envelope.OccurredAt.IsZero() {
return nil, merrors.InvalidArgument("occurred_at is required", "occurred_at")
}
if len(envelope.Data) == 0 {
envelope.Data = []byte("{}")
}
envelope.EventID = strings.TrimSpace(envelope.EventID)
envelope.Type = strings.TrimSpace(envelope.Type)
envelope.ClientID = strings.TrimSpace(envelope.ClientID)
envelope.OccurredAt = envelope.OccurredAt.UTC()
if !envelope.PublishedAt.IsZero() {
envelope.PublishedAt = envelope.PublishedAt.UTC()
}
return &envelope, nil
}
func (s *parserService) BuildPayload(_ context.Context, envelope *Envelope) ([]byte, error) {
if envelope == nil {
return nil, merrors.InvalidArgument("event envelope is required", "envelope")
}
payload := Payload{
EventID: envelope.EventID,
Type: envelope.Type,
ClientID: envelope.ClientID,
OccurredAt: envelope.OccurredAt.UTC().Format(time.RFC3339Nano),
Data: envelope.Data,
}
if !envelope.PublishedAt.IsZero() {
payload.PublishedAt = envelope.PublishedAt.UTC().Format(time.RFC3339Nano)
}
data, err := json.Marshal(payload)
if err != nil {
s.logger.Warn("Failed to marshal callback payload", zap.Error(err), zap.String("event_id", envelope.EventID))
return nil, merrors.InternalWrap(err, "failed to marshal callback payload")
}
return data, nil
}