63 lines
2.3 KiB
Go
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)
|
|
}
|