This project implements a simple banking API with basic functionalities such as credit and debit transactions, along with idempotency support to ensure that duplicate or replayed requests do not result in inconsistent transaction states. The application is built in Golang and uses thread-safe mechanisms for processing transactions to ensure consistency, even under high concurrency.
- Credit Transaction: Adds funds to a user's account.
- Debit Transaction: Deducts funds from a user's account.
- Idempotency Support: Ensures that duplicate requests do not result in multiple executions of the same transaction.
- Thread-Safe Transactions: Ensures transactions are atomic and consistent in multi-threaded environments.
- External Integration: Supports forwarding transaction information to third-party systems.
- Error Handling and Logging: Detailed error handling for different transaction failure scenarios.
-
Clone the repository:
git clone https://github.com/midedickson/simple-banking-app.git
-
Navigate into the project directory:
cd simple-banking-app
-
Install dependencies:
go mod tidy
-
Set up your environment variables, which may include database connection strings, third-party service keys, etc.
-
Start the server:
go run main.go
-
The API will be available on
http://localhost:8080
.
- GET
/
- Simple endpoint to verify if the server is running.
- Response:
"hello, you have reached simple banking api"
- POST
/transaction/credit
- Requires an
X-Idempotency-Key
in the request header. - Body:
{ "account_id": "string", "amount": "float" }
- Response: Success message or appropriate error (e.g., insufficient funds, duplicate idempotency key).
- Requires an
- POST
/transaction/debit
- Similar to the credit endpoint, but it deducts funds.
- Requires an
X-Idempotency-Key
in the request header. - Body:
{ "account_id": "string", "amount": "float" }
- GET
/idempotency
- Generates a new idempotency key for making transactions.
- Response includes the generated
X-Idempotency-Key
in the response header and body.
- GET
/transaction/{reference}
- Retrieves the details of a specific transaction using the transaction reference.
- GET
/account/{id}
- Fetches the details of a specific user's account by
id
.
- Fetches the details of a specific user's account by
Idempotency is a key feature in ensuring that duplicate requests do not result in the duplication of transactions. This is particularly important in financial applications where retrying or replaying the same request due to network issues or user actions can cause unintended outcomes.
How Idempotency Works:
- A client sends a request to the server with an
X-Idempotency-Key
header. - The server checks if the idempotency key has already been used for a transaction:
- If the key is new: The server processes the request and stores the idempotency key with the transaction status.
- If the key is in progress (
PROCESSING
): The server rejects the request to avoid duplicate processing. - If the key is successful (
SUCCESS
): The server returns the result of the original transaction. - If the key failed (
FAILED
): The server allows the request to be retried.
This ensures that even if a client retries a request (e.g., due to a network timeout), the transaction will only be processed once.
In a concurrent environment, multiple transactions might be processed simultaneously, potentially leading to inconsistent account states if proper precautions are not taken. To avoid this, thread safety is implemented to ensure that transactions are atomic and consistent.
- Atomicity: Each transaction (credit or debit) is processed in isolation, ensuring that no other transaction interferes with its execution.
- Locks/Mutexes: Appropriate locking mechanisms are applied when updating account balances or creating transactions to avoid race conditions.
- External Transaction Handling: The system ensures that all updates to accounts and communication with external systems (e.g., third-party transaction processors) are coordinated to prevent issues like double processing or lost updates.
- Concurrency: Multiple requests can be processed at the same time without the risk of data corruption.
- Consistency: Account balances remain consistent even when several transactions are processed in parallel.
Tests are available to ensure that the idempotency, thread safety, and transaction logic are functioning as expected.
To run the tests, use:
go test ./...
This command will run all the tests within the project.
- Fork the repository.
- Create a new feature branch (
git checkout -b feature/my-feature
). - Make your changes.
- Commit your changes (
git commit -m 'Add new feature'
). - Push to your branch (
git push origin feature/my-feature
). - Open a pull request to the
main
branch.
This project is licensed under the MIT License. See the LICENSE
file for more details.
Feel free to reach out with any questions or suggestions for improvements.