Files
GL/application/settlement/service.go
T

63 lines
2.3 KiB
Go

package settlement
import (
"context"
"crypto/rand"
"encoding/hex"
"fmt"
"time"
"gl/domain/ledger"
)
type EnqueueRepository interface {
Enqueue(context.Context, ledger.Settlement) (ledger.Settlement, bool, error)
Get(context.Context, string, string) (ledger.Settlement, error)
RetryByOperator(context.Context, string, string, string, time.Time) (ledger.Settlement, error)
}
func (s *Service) RetryByOperator(ctx context.Context, settlementID, actorID, reason string) (ledger.Settlement, error) {
if settlementID == "" || actorID == "" || reason == "" {
return ledger.Settlement{}, fmt.Errorf("settlement id, actor id, and reason are required")
}
now := time.Now().UTC()
if s.now != nil {
now = s.now().UTC()
}
return s.repository.RetryByOperator(ctx, settlementID, actorID, reason, now)
}
type Service struct {
repository EnqueueRepository
now func() time.Time
}
func NewService(repository EnqueueRepository) *Service { return &Service{repository: repository} }
func (s *Service) Enqueue(ctx context.Context, sourceService, sourceTxID, idempotencyKey, network, xdr string) (ledger.Settlement, bool, error) {
if sourceService == "" || sourceTxID == "" || idempotencyKey == "" || network == "" || xdr == "" {
return ledger.Settlement{}, false, fmt.Errorf("settlement identity, network, and signed transaction are required")
}
id := make([]byte, 16)
if _, err := rand.Read(id); err != nil {
return ledger.Settlement{}, false, fmt.Errorf("generate settlement id: %w", err)
}
now := time.Now().UTC()
if s.now != nil {
now = s.now().UTC()
}
encoded := hex.EncodeToString(id)
record := ledger.Settlement{ID: encoded[0:8] + "-" + encoded[8:12] + "-" + encoded[12:16] + "-" + encoded[16:20] + "-" + encoded[20:], SourceService: sourceService, SourceTxID: sourceTxID, IdempotencyKey: idempotencyKey, Status: ledger.SettlementPending, Network: network, SignedTransactionXDR: xdr, AvailableAt: now}
if err := record.Validate(); err != nil {
return ledger.Settlement{}, false, err
}
return s.repository.Enqueue(ctx, record)
}
func (s *Service) Get(ctx context.Context, settlementID, idempotencyKey string) (ledger.Settlement, error) {
if settlementID == "" && idempotencyKey == "" {
return ledger.Settlement{}, fmt.Errorf("settlement id or idempotency key is required")
}
return s.repository.Get(ctx, settlementID, idempotencyKey)
}