Hone logo
Hone
Problems

Concurrent Transaction Processing System

This challenge asks you to design and implement a simplified transaction processing system in Go. The system should handle concurrent transactions safely, ensuring data consistency even when multiple transactions attempt to modify the same data simultaneously. This is a fundamental problem in distributed systems and databases, and understanding its implementation is crucial for building robust applications.

Problem Description

You are tasked with building a system that manages a bank account balance. The system should allow concurrent transactions (deposits and withdrawals) to be processed safely. The core requirement is to ensure that the balance remains consistent even with multiple concurrent operations.

Specifically, you need to implement the following:

  1. BankAccount struct: This struct represents a bank account and contains a single field: balance (float64).
  2. Deposit(amount float64) method: This method adds the given amount to the account balance. It must be thread-safe.
  3. Withdraw(amount float64) method: This method subtracts the given amount from the account balance. It must be thread-safe and should return an error if the withdrawal would result in a negative balance.
  4. GetBalance() float64 method: This method returns the current account balance. It should be thread-safe.
  5. TransactionProcessor struct: This struct encapsulates the BankAccount and provides a thread-safe interface for processing transactions. It should handle concurrent access to the account balance.
  6. ProcessTransaction(transactionType string, amount float64) float64 method: This method takes a transaction type ("deposit" or "withdrawal") and an amount as input. It performs the corresponding operation on the bank account and returns the updated balance. It should return an error if the transaction type is invalid.

Examples

Example 1:

Input:
BankAccount: balance = 100.0
Concurrent Transactions:
  - Deposit(50.0)
  - Withdrawal(25.0)
Output:
BankAccount: balance = 125.0

Explanation: The deposit adds 50.0 to the balance (100.0 + 50.0 = 150.0). The withdrawal then subtracts 25.0 (150.0 - 25.0 = 125.0). The order of operations is not guaranteed, but the final balance must be 125.0.

Example 2:

Input:
BankAccount: balance = 50.0
Transaction: Withdrawal(75.0)
Output:
BankAccount: balance = 50.0
Error: "insufficient funds"

Explanation: The withdrawal amount (75.0) is greater than the current balance (50.0). The withdrawal is rejected, and the balance remains unchanged. An error is returned.

Example 3: (Concurrent Scenario)

Input:
BankAccount: balance = 200.0
Concurrent Transactions:
  - Withdrawal(100.0)
  - Deposit(75.0)
  - Withdrawal(50.0)
Output:
BankAccount: balance = 125.0

Explanation: Even with concurrent operations, the final balance must be 125.0. The system must prevent race conditions and ensure that the balance is updated correctly.

Constraints

  • balance must always be a non-negative number.
  • amount in Deposit and Withdraw must be positive numbers.
  • The system must handle at least 10 concurrent transactions without data corruption or deadlocks. (This is a functional requirement, not a performance benchmark).
  • Transaction types must be case-insensitive ("deposit" or "withdrawal").
  • Error messages should be descriptive and informative.

Notes

  • Use Go's built-in sync package (e.g., sync.Mutex) to ensure thread safety.
  • Consider using a WaitGroup to wait for all transactions to complete.
  • Focus on correctness and thread safety. Performance optimization is not the primary goal.
  • Think about how to handle potential race conditions when multiple goroutines are accessing and modifying the balance concurrently. A mutex is a good starting point.
  • Error handling is important. Return meaningful errors to indicate failures.
  • The ProcessTransaction method should not directly modify the BankAccount's balance. It should call the Deposit or Withdraw methods.
Loading editor...
go