Skip to content

[Feature Request]: Transaction Abstraction Refactoring #1243

@beesaferoot

Description

@beesaferoot

Preflight Checklist

Problem Description

The current MPM transaction system functions reliably in most cases, but over time it has accumulated architectural constraints that make it difficult to maintain, reason about, and extend. These issues increasingly surface as the system grows in complexity and transaction volume.

1. Complex Model Relationships

The transaction domain relies on deeply coupled and highly interconnected models, making the system hard to understand and modify safely.

Image

Impact:
High cognitive overhead for contributors, increased risk of regressions, and limited flexibility for future changes.

2. Inconsistent Transaction Flows

Different transaction types follow significantly different execution paths.
CashTransaction, for example, operates under a markedly different flow compared to other transaction types. The rationale for this divergence is unclear, and it is not obvious whether this approach provides any architectural or operational advantage.

Impact:
Increased complexity, duplicated logic, and difficulty enforcing consistent guarantees across transaction types.

3. Limited Retry Support

Retry logic is implemented only in TokenProcessor (3 attempts with a fixed 5-second delay). Other critical stages do not support retries:

  • Validation failures → immediate failure

  • Database errors during payment distribution → permanent failure

  • SMS notification failures → silent failure

Impact:
Transient issues (network timeouts, rate limits, temporary database errors) result in irreversible transaction failures, often requiring manual intervention.

4. Implicit and Fragmented State Management

Transaction state is spread across multiple fields and models, with no single authoritative source of truth:

  • Transaction.type is mutated during processing

  • Provider-specific status codes vary (1 = success, 0 = pending, -1 = failed)

  • No explicit tracking of processing stages or failure points

Impact:
It is difficult to:

  • Identify “stuck” or partially processed transactions

  • Resume processing from the point of failure

  • Build reliable monitoring or observability dashboards

5. Partial Idempotency Guarantees

Idempotency is enforced only during token generation. Other stages—particularly payment distribution—lack idempotency safeguards:

// ApplianceInstallmentPayer - If retried, will pay installments AGAIN
$installment->remaining -= $this->transaction->amount;

Impact:
Most operations cannot be safely retried. Re-dispatching jobs risks duplicate payments and inconsistent financial state.

6. Incomplete Compensation and Rollback Handling

Rollback logic exists only in TokenProcessor, and only when token generation fails:

Impact:

  • Failures after partial payment distribution leave orphaned records

  • No compensation logic exists for access rate payments

  • The system cannot guarantee transactional consistency across stages

7. Hardcoded Payment Provider Resolution

TransactionAdapter relies on instanceof checks to resolve payment providers:

if ($provider instanceof AgentTransaction) { ... }
elseif ($provider instanceof SwiftaTransaction) { ... }
elseif ($provider instanceof PaystackTransaction) { ... }

Impact:

  • Adding a new provider requires modifying core logic

  • Violates the Open/Closed Principle

  • Encourages tight coupling between transaction orchestration and provider implementations

Proposed Solution

To address these limitations, we need to explore a more robust abstraction model for transaction processing that:

  • Standardizes transaction flows

  • Makes state explicit and observable

  • Enables safe retries and idempotent operations

  • Supports well-defined compensation strategies

  • Decouples provider integrations from core transaction logic

The next steps involve:

  • Sketching an ideal abstraction model for transactions

  • Evaluating implementation feasibility and migration paths

This work will serve as the foundation for a more resilient, extensible, and maintainable transaction system within MPM.

Alternatives Considered

N/A

Additional Information

No response

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions