// Package getdelivery implements trusted operator lookup of one accepted mail // delivery. package getdelivery import ( "context" "errors" "fmt" "galaxy/mail/internal/domain/common" deliverydomain "galaxy/mail/internal/domain/delivery" ) var ( // ErrNotFound reports that the requested delivery does not exist. ErrNotFound = errors.New("get delivery not found") // ErrServiceUnavailable reports that trusted lookup could not load durable // state safely. ErrServiceUnavailable = errors.New("get delivery service unavailable") ) // Input stores one exact trusted lookup by delivery identifier. type Input struct { // DeliveryID stores the exact accepted delivery identifier to resolve. DeliveryID common.DeliveryID } // Validate reports whether input contains a complete lookup key. func (input Input) Validate() error { if err := input.DeliveryID.Validate(); err != nil { return fmt.Errorf("delivery id: %w", err) } return nil } // Result stores one full delivery record and its optional dead-letter entry. type Result struct { // Delivery stores the resolved accepted delivery record. Delivery deliverydomain.Delivery // DeadLetter stores the optional dead-letter entry when Delivery is in the // `dead_letter` terminal state. DeadLetter *deliverydomain.DeadLetterEntry } // Validate reports whether result contains a consistent delivery view. func (result Result) Validate() error { if err := result.Delivery.Validate(); err != nil { return fmt.Errorf("delivery: %w", err) } if err := deliverydomain.ValidateDeadLetterState(result.Delivery, result.DeadLetter); err != nil { return fmt.Errorf("dead-letter state: %w", err) } return nil } // Store provides exact lookup of one accepted delivery and its dead-letter // entry. type Store interface { // GetDelivery loads one accepted delivery by its identifier. GetDelivery(context.Context, common.DeliveryID) (deliverydomain.Delivery, bool, error) // GetDeadLetter loads the dead-letter entry associated with deliveryID when // one exists. GetDeadLetter(context.Context, common.DeliveryID) (deliverydomain.DeadLetterEntry, bool, error) } // Config stores the dependencies used by Service. type Config struct { // Store owns durable delivery and dead-letter state. Store Store } // Service executes trusted exact delivery lookups. type Service struct { store Store } // New constructs Service from cfg. func New(cfg Config) (*Service, error) { if cfg.Store == nil { return nil, errors.New("new get delivery service: nil store") } return &Service{store: cfg.Store}, nil } // Execute loads one accepted delivery and its optional dead-letter entry. func (service *Service) Execute(ctx context.Context, input Input) (Result, error) { if ctx == nil { return Result{}, errors.New("execute get delivery: nil context") } if service == nil { return Result{}, errors.New("execute get delivery: nil service") } if err := input.Validate(); err != nil { return Result{}, fmt.Errorf("execute get delivery: %w", err) } record, found, err := service.store.GetDelivery(ctx, input.DeliveryID) switch { case err != nil: return Result{}, fmt.Errorf("%w: load delivery: %v", ErrServiceUnavailable, err) case !found: return Result{}, ErrNotFound } result := Result{Delivery: record} if record.Status == deliverydomain.StatusDeadLetter { entry, found, err := service.store.GetDeadLetter(ctx, input.DeliveryID) switch { case err != nil: return Result{}, fmt.Errorf("%w: load dead-letter entry: %v", ErrServiceUnavailable, err) case !found: return Result{}, fmt.Errorf("%w: missing dead-letter entry for delivery %q", ErrServiceUnavailable, input.DeliveryID) default: result.DeadLetter = &entry } } if err := result.Validate(); err != nil { return Result{}, fmt.Errorf("%w: invalid result: %v", ErrServiceUnavailable, err) } return result, nil }