package mailstore import ( "context" "database/sql" "errors" "fmt" pgtable "galaxy/mail/internal/adapters/postgres/jet/mail/table" "galaxy/mail/internal/domain/common" deliverydomain "galaxy/mail/internal/domain/delivery" "galaxy/mail/internal/domain/idempotency" "galaxy/mail/internal/service/acceptgenericdelivery" ) // GenericAcceptance returns a handle that satisfies // acceptgenericdelivery.Store. Generic and auth acceptance share the same // idempotency / delivery read paths but the write input types differ — the // adapter avoids a method-name conflict on Store.CreateAcceptance. func (store *Store) GenericAcceptance() *GenericAcceptanceStore { return &GenericAcceptanceStore{store: store} } // GenericAcceptanceStore is the acceptgenericdelivery.Store handle returned // by Store.GenericAcceptance. It defers to the umbrella store for shared // reads. type GenericAcceptanceStore struct { store *Store } var _ acceptgenericdelivery.Store = (*GenericAcceptanceStore)(nil) // CreateAcceptance writes one generic-delivery acceptance write set inside // one BEGIN … COMMIT transaction. Idempotency races surface as // acceptgenericdelivery.ErrConflict. func (handle *GenericAcceptanceStore) CreateAcceptance(ctx context.Context, input acceptgenericdelivery.CreateAcceptanceInput) error { if handle == nil || handle.store == 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) } return handle.store.withTx(ctx, "create generic acceptance", func(ctx context.Context, tx *sql.Tx) error { first := input.FirstAttempt if err := insertDelivery(ctx, tx, input.Delivery, input.Idempotency, input.Idempotency.ExpiresAt, &first); err != nil { if isUniqueViolation(err) { return acceptgenericdelivery.ErrConflict } return fmt.Errorf("create generic acceptance: insert delivery: %w", err) } if err := insertAttempt(ctx, tx, input.FirstAttempt); err != nil { return fmt.Errorf("create generic acceptance: insert first attempt: %w", err) } if input.DeliveryPayload != nil { payload, err := marshalDeliveryPayload(*input.DeliveryPayload) if err != nil { return fmt.Errorf("create generic acceptance: %w", err) } payloadStmt := pgtable.DeliveryPayloads.INSERT( pgtable.DeliveryPayloads.DeliveryID, pgtable.DeliveryPayloads.Payload, ).VALUES( input.Delivery.DeliveryID.String(), payload, ) payloadQuery, payloadArgs := payloadStmt.Sql() if _, err := tx.ExecContext(ctx, payloadQuery, payloadArgs...); err != nil { return fmt.Errorf("create generic acceptance: insert delivery payload: %w", err) } } return nil }) } // GetIdempotency forwards to the umbrella store. func (handle *GenericAcceptanceStore) GetIdempotency(ctx context.Context, source deliverydomain.Source, key common.IdempotencyKey) (idempotency.Record, bool, error) { return handle.store.GetIdempotency(ctx, source, key) } // GetDelivery forwards to the umbrella store. func (handle *GenericAcceptanceStore) GetDelivery(ctx context.Context, deliveryID common.DeliveryID) (deliverydomain.Delivery, bool, error) { return handle.store.GetDelivery(ctx, deliveryID) }