87 lines
2.4 KiB
Go
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.mongodb.org/mongo-driver/v2/bson"
|
|
"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 envelope.OrganizationRef == bson.NilObjectID {
|
|
return nil, merrors.InvalidArgument("organization_ref is required", "organization_ref")
|
|
}
|
|
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.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,
|
|
OrganizationRef: envelope.OrganizationRef,
|
|
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
|
|
}
|