RejectTransaction rejects a transaction by updating its status and recording the rejection reason. It starts a tracing span, updates the transaction status and metadata, persists the transaction, and records relevant events and errors. Parameters: - ctx context.Context: The context for the operatio
(ctx context.Context, transaction *model.Transaction, reason string)
| 1679 | // - *model.Transaction: A pointer to the rejected Transaction model. |
| 1680 | // - error: An error if the transaction could not be recorded. |
| 1681 | func (l *LedgerForge) RejectTransaction(ctx context.Context, transaction *model.Transaction, reason string) (*model.Transaction, error) { |
| 1682 | ctx, span := tracer.Start(ctx, "RejectTransaction") |
| 1683 | defer span.End() |
| 1684 | |
| 1685 | // Update the transaction status to rejected |
| 1686 | transaction.Status = StatusRejected |
| 1687 | |
| 1688 | // Initialize MetaData if it's nil and add the rejection reason |
| 1689 | if transaction.MetaData == nil { |
| 1690 | transaction.MetaData = make(map[string]interface{}) |
| 1691 | } |
| 1692 | transaction.MetaData["ledgerforge_rejection_reason"] = reason |
| 1693 | |
| 1694 | // Persist the transaction with the updated status and metadata |
| 1695 | transaction, err := l.datasource.RecordTransaction(ctx, transaction) |
| 1696 | if err != nil { |
| 1697 | span.RecordError(err) |
| 1698 | logrus.WithError(err).Error("failed to save transaction to db") |
| 1699 | return nil, err |
| 1700 | } |
| 1701 | |
| 1702 | span.AddEvent("Transaction rejected", trace.WithAttributes(attribute.String("transaction.id", transaction.TransactionID))) |
| 1703 | |
| 1704 | // Record rejection metrics. |
| 1705 | rejectionReason := categorizeRejectionReason(reason) |
| 1706 | metrics.TransactionRejectedTotal.Add(ctx, 1, |
| 1707 | otelmetric.WithAttributes(attribute.String("reason", rejectionReason)), |
| 1708 | ) |
| 1709 | metrics.TransactionTotal.Add(ctx, 1, |
| 1710 | otelmetric.WithAttributes( |
| 1711 | attribute.String("status", StatusRejected), |
| 1712 | attribute.String("currency", transaction.Currency), |
| 1713 | ), |
| 1714 | ) |
| 1715 | |
| 1716 | if transaction.Atomic { |
| 1717 | logrus.Info(transaction.ParentTransaction, "parent transaction", transaction.Atomic, "atomic", transaction.Inflight, "inflight") |
| 1718 | parentTransactionID, ok := transaction.MetaData["QUEUED_PARENT_TRANSACTION"].(string) |
| 1719 | if !ok { |
| 1720 | return nil, fmt.Errorf("parent transaction ID not found in meta data") |
| 1721 | } |
| 1722 | l.handleAsyncBulkTransactionFailure(ctx, errors.New("transaction rejected"), parentTransactionID, transaction.Atomic, transaction.Inflight) |
| 1723 | } |
| 1724 | // For rejected transactions, no balances were updated, so pass nil |
| 1725 | l.postTransactionActions(ctx, transaction, nil, nil) |
| 1726 | return transaction, nil |
| 1727 | } |
| 1728 | |
| 1729 | // categorizeRejectionReason maps a free-text rejection reason to a bounded set of metric labels |
| 1730 | // to keep Prometheus cardinality under control. |