feat: mail service
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
package redisstate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"galaxy/mail/internal/domain/common"
|
||||
deliverydomain "galaxy/mail/internal/domain/delivery"
|
||||
"galaxy/mail/internal/domain/idempotency"
|
||||
"galaxy/mail/internal/service/acceptgenericdelivery"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// GenericAcceptanceStore provides the Redis-backed durable storage used by the
|
||||
// generic-delivery acceptance use case.
|
||||
type GenericAcceptanceStore struct {
|
||||
client *redis.Client
|
||||
writer *AtomicWriter
|
||||
keys Keyspace
|
||||
}
|
||||
|
||||
// NewGenericAcceptanceStore constructs one Redis-backed generic acceptance
|
||||
// store.
|
||||
func NewGenericAcceptanceStore(client *redis.Client) (*GenericAcceptanceStore, error) {
|
||||
if client == nil {
|
||||
return nil, errors.New("new generic acceptance store: nil redis client")
|
||||
}
|
||||
|
||||
writer, err := NewAtomicWriter(client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("new generic acceptance store: %w", err)
|
||||
}
|
||||
|
||||
return &GenericAcceptanceStore{
|
||||
client: client,
|
||||
writer: writer,
|
||||
keys: Keyspace{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateAcceptance stores one generic-delivery acceptance write set in Redis.
|
||||
func (store *GenericAcceptanceStore) CreateAcceptance(ctx context.Context, input acceptgenericdelivery.CreateAcceptanceInput) error {
|
||||
if store == nil || store.client == nil || store.writer == nil {
|
||||
return errors.New("create generic acceptance: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return errors.New("create generic acceptance: nil context")
|
||||
}
|
||||
if err := input.Validate(); err != nil {
|
||||
return fmt.Errorf("create generic acceptance: %w", err)
|
||||
}
|
||||
|
||||
writerInput := CreateAcceptanceInput{
|
||||
Delivery: input.Delivery,
|
||||
FirstAttempt: &input.FirstAttempt,
|
||||
Idempotency: &input.Idempotency,
|
||||
}
|
||||
if input.DeliveryPayload != nil {
|
||||
writerInput.DeliveryPayload = input.DeliveryPayload
|
||||
}
|
||||
|
||||
err := store.writer.CreateAcceptance(ctx, writerInput)
|
||||
if errors.Is(err, ErrConflict) {
|
||||
return fmt.Errorf("create generic acceptance: %w", acceptgenericdelivery.ErrConflict)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("create generic acceptance: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetIdempotency loads one accepted idempotency scope from Redis.
|
||||
func (store *GenericAcceptanceStore) GetIdempotency(ctx context.Context, source deliverydomain.Source, key common.IdempotencyKey) (idempotency.Record, bool, error) {
|
||||
if store == nil || store.client == nil {
|
||||
return idempotency.Record{}, false, errors.New("get generic acceptance idempotency: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return idempotency.Record{}, false, errors.New("get generic acceptance idempotency: nil context")
|
||||
}
|
||||
|
||||
payload, err := store.client.Get(ctx, store.keys.Idempotency(source, key)).Bytes()
|
||||
switch {
|
||||
case errors.Is(err, redis.Nil):
|
||||
return idempotency.Record{}, false, nil
|
||||
case err != nil:
|
||||
return idempotency.Record{}, false, fmt.Errorf("get generic acceptance idempotency: %w", err)
|
||||
}
|
||||
|
||||
record, err := UnmarshalIdempotency(payload)
|
||||
if err != nil {
|
||||
return idempotency.Record{}, false, fmt.Errorf("get generic acceptance idempotency: %w", err)
|
||||
}
|
||||
|
||||
return record, true, nil
|
||||
}
|
||||
|
||||
// GetDelivery loads one accepted delivery by its identifier.
|
||||
func (store *GenericAcceptanceStore) GetDelivery(ctx context.Context, deliveryID common.DeliveryID) (deliverydomain.Delivery, bool, error) {
|
||||
if store == nil || store.client == nil {
|
||||
return deliverydomain.Delivery{}, false, errors.New("get generic acceptance delivery: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return deliverydomain.Delivery{}, false, errors.New("get generic acceptance delivery: nil context")
|
||||
}
|
||||
|
||||
payload, err := store.client.Get(ctx, store.keys.Delivery(deliveryID)).Bytes()
|
||||
switch {
|
||||
case errors.Is(err, redis.Nil):
|
||||
return deliverydomain.Delivery{}, false, nil
|
||||
case err != nil:
|
||||
return deliverydomain.Delivery{}, false, fmt.Errorf("get generic acceptance delivery: %w", err)
|
||||
}
|
||||
|
||||
record, err := UnmarshalDelivery(payload)
|
||||
if err != nil {
|
||||
return deliverydomain.Delivery{}, false, fmt.Errorf("get generic acceptance delivery: %w", err)
|
||||
}
|
||||
|
||||
return record, true, nil
|
||||
}
|
||||
|
||||
// GetDeliveryPayload loads one raw accepted attachment bundle by delivery id.
|
||||
func (store *GenericAcceptanceStore) GetDeliveryPayload(ctx context.Context, deliveryID common.DeliveryID) (acceptgenericdelivery.DeliveryPayload, bool, error) {
|
||||
if store == nil || store.client == nil {
|
||||
return acceptgenericdelivery.DeliveryPayload{}, false, errors.New("get generic acceptance delivery payload: nil store")
|
||||
}
|
||||
if ctx == nil {
|
||||
return acceptgenericdelivery.DeliveryPayload{}, false, errors.New("get generic acceptance delivery payload: nil context")
|
||||
}
|
||||
|
||||
payload, err := store.client.Get(ctx, store.keys.DeliveryPayload(deliveryID)).Bytes()
|
||||
switch {
|
||||
case errors.Is(err, redis.Nil):
|
||||
return acceptgenericdelivery.DeliveryPayload{}, false, nil
|
||||
case err != nil:
|
||||
return acceptgenericdelivery.DeliveryPayload{}, false, fmt.Errorf("get generic acceptance delivery payload: %w", err)
|
||||
}
|
||||
|
||||
record, err := UnmarshalDeliveryPayload(payload)
|
||||
if err != nil {
|
||||
return acceptgenericdelivery.DeliveryPayload{}, false, fmt.Errorf("get generic acceptance delivery payload: %w", err)
|
||||
}
|
||||
|
||||
return record, true, nil
|
||||
}
|
||||
Reference in New Issue
Block a user