idempotency key usage fix

This commit is contained in:
Stephan D
2026-01-21 15:23:50 +01:00
parent a15375f18e
commit d2e78356e6
48 changed files with 729 additions and 559 deletions

View File

@@ -10,6 +10,7 @@ import (
storageMongo "github.com/tech/sendico/ledger/storage/mongo"
"github.com/tech/sendico/pkg/api/routers/gsresponse"
"github.com/tech/sendico/pkg/merrors"
"github.com/tech/sendico/pkg/mutil/mzap"
ledgerv1 "github.com/tech/sendico/pkg/proto/ledger/v1"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
@@ -53,13 +54,19 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
if err != nil {
return nil, err
}
logger := s.logger.With(
zap.String("idempotency_key", req.IdempotencyKey),
mzap.ObjRef("organization_ref", orgRef),
mzap.ObjRef("from_account_ref", fromAccountRef),
mzap.ObjRef("to_account_ref", toAccountRef),
zap.String("currency", req.Money.Currency),
)
// Check for duplicate idempotency key
existingEntry, err := s.storage.JournalEntries().GetByIdempotencyKey(ctx, orgRef, req.IdempotencyKey)
if err == nil && existingEntry != nil {
recordDuplicateRequest("transfer")
s.logger.Info("duplicate transfer request (idempotency)",
zap.String("idempotencyKey", req.IdempotencyKey),
logger.Info("duplicate transfer request (idempotency)",
zap.String("existingEntryID", existingEntry.GetID().Hex()))
return &ledgerv1.PostResponse{
JournalEntryRef: existingEntry.GetID().Hex(),
@@ -68,7 +75,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
}, nil
}
if err != nil && err != storage.ErrJournalEntryNotFound {
s.logger.Warn("failed to check idempotency", zap.Error(err))
logger.Warn("failed to check idempotency", zap.Error(err))
return nil, merrors.Internal("failed to check idempotency")
}
@@ -78,7 +85,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
if err == storage.ErrAccountNotFound {
return nil, merrors.NoData("from_account not found")
}
s.logger.Warn("failed to get from_account", zap.Error(err))
logger.Warn("failed to get from_account", zap.Error(err))
return nil, merrors.Internal("failed to get from_account")
}
if err := validateAccountForOrg(fromAccount, orgRef, req.Money.Currency); err != nil {
@@ -90,7 +97,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
if err == storage.ErrAccountNotFound {
return nil, merrors.NoData("to_account not found")
}
s.logger.Warn("failed to get to_account", zap.Error(err))
logger.Warn("failed to get to_account", zap.Error(err))
return nil, merrors.Internal("failed to get to_account")
}
if err := validateAccountForOrg(toAccount, orgRef, req.Money.Currency); err != nil {
@@ -147,7 +154,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
if err == storage.ErrAccountNotFound {
return nil, merrors.NoData(fmt.Sprintf("charges[%d]: account not found", i))
}
s.logger.Warn("failed to get charge account", zap.Error(err), zap.String("chargeAccountRef", chargeAccountRef.Hex()))
logger.Warn("failed to get charge account", zap.Error(err), zap.String("chargeAccountRef", chargeAccountRef.Hex()))
return nil, merrors.Internal("failed to get charge account")
}
if err := validateAccountForOrg(chargeAccount, orgRef, charge.Money.Currency); err != nil {
@@ -188,7 +195,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
entry.OrganizationRef = orgRef
if err := s.storage.JournalEntries().Create(txCtx, entry); err != nil {
s.logger.Warn("failed to create journal entry", zap.Error(err))
logger.Warn("failed to create journal entry", zap.Error(err))
return nil, merrors.Internal("failed to create journal entry")
}
@@ -206,7 +213,7 @@ func (s *Service) transferResponder(_ context.Context, req *ledgerv1.TransferReq
}
if err := s.storage.PostingLines().CreateMany(txCtx, postingLines); err != nil {
s.logger.Warn("failed to create posting lines", zap.Error(err))
logger.Warn("failed to create posting lines", zap.Error(err))
return nil, merrors.Internal("failed to create posting lines")
}