You've already forked transaction-tracker
Initial project 🎉
This commit is contained in:
148
README.md
Normal file
148
README.md
Normal file
@@ -0,0 +1,148 @@
|
||||
# Transaction Tracker
|
||||
|
||||
A lightweight Python library for tracking processed transactions with automatic TTL (Time-To-Live) functionality. This library helps prevent duplicate transaction processing by maintaining a record of previously processed transactions.
|
||||
|
||||
## Features
|
||||
|
||||
- **Simple file-based storage**: Transactions are stored as individual JSON files on disk
|
||||
- **Automatic TTL**: Records automatically expire after a configurable period (default: 3 days)
|
||||
- **Decorator syntax**: Easy-to-use decorator for making functions transaction-safe
|
||||
- **No external dependencies**: Uses only Python standard library modules
|
||||
- **Customizable**: Configure storage location and TTL period to suit your needs
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://hub.cybercinch.nz/cybercinch/transaction-tracker.git
|
||||
|
||||
# Copy the transaction_tracker.py file to your project
|
||||
cp transaction-tracker/transaction_tracker.py /path/to/your/project/
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from transaction_tracker import TransactionProcessor, TransactionAlreadyProcessedError
|
||||
|
||||
# Create a transaction processor
|
||||
processor = TransactionProcessor(storage_dir="transaction_records", ttl_days=3)
|
||||
|
||||
# Define a transaction processing function
|
||||
@processor.unique_transaction()
|
||||
def process_payment(transaction_id, amount, user_id):
|
||||
print(f"Processing ${amount} payment for user {user_id}")
|
||||
# Your actual payment processing logic here
|
||||
return {"status": "success", "amount": amount}
|
||||
|
||||
# Use your decorated function
|
||||
try:
|
||||
# This will succeed
|
||||
result = process_payment("tx123", 100.00, "user456")
|
||||
print(f"Payment result: {result}")
|
||||
|
||||
# This will fail (duplicate transaction)
|
||||
result = process_payment("tx123", 100.00, "user456")
|
||||
except TransactionAlreadyProcessedError as e:
|
||||
print(f"Expected error: {e}")
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
1. Create a `TransactionProcessor` instance
|
||||
2. Decorate your transaction processing functions with `@processor.unique_transaction()`
|
||||
3. Handle the `TransactionAlreadyProcessedError` exception for duplicate transactions
|
||||
|
||||
```python
|
||||
from transaction_tracker import TransactionProcessor, TransactionAlreadyProcessedError
|
||||
import logging
|
||||
|
||||
# Configure logging (optional)
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# Create processor with custom TTL and storage location
|
||||
processor = TransactionProcessor(
|
||||
storage_dir="/path/to/storage",
|
||||
ttl_days=7 # Keep records for 7 days
|
||||
)
|
||||
|
||||
# Decorate your function
|
||||
@processor.unique_transaction()
|
||||
def process_refund(transaction_id, amount, customer_id):
|
||||
# Your refund processing logic
|
||||
print(f"Processing refund of ${amount} for customer {customer_id}")
|
||||
return {"status": "refunded", "amount": amount}
|
||||
|
||||
# Use your function and handle potential duplicates
|
||||
try:
|
||||
result = process_refund("refund_001", 50.00, "customer123")
|
||||
print(f"Refund processed: {result}")
|
||||
except TransactionAlreadyProcessedError:
|
||||
print("This refund was already processed")
|
||||
```
|
||||
|
||||
### Custom Transaction ID Parameter
|
||||
|
||||
If your function uses a different parameter name for the transaction ID:
|
||||
|
||||
```python
|
||||
@processor.unique_transaction(id_arg='refund_id')
|
||||
def process_refund(refund_id, amount, customer_id):
|
||||
# Function uses refund_id instead of transaction_id
|
||||
return {"status": "refunded", "amount": amount}
|
||||
```
|
||||
|
||||
### Manual Cleanup
|
||||
|
||||
Records are automatically cleaned up when the processor is initialized, but you can also trigger cleanup manually:
|
||||
|
||||
```python
|
||||
# Clean up expired transactions
|
||||
processor.cleanup()
|
||||
|
||||
# Reset/clear all transaction records
|
||||
processor.reset()
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. When a decorated function is called, the processor checks if the transaction ID has been processed before
|
||||
2. If the transaction is new, the function executes normally and the transaction is marked as processed
|
||||
3. If the transaction was already processed, a `TransactionAlreadyProcessedError` is raised
|
||||
4. Transaction records automatically expire after the configured TTL period
|
||||
|
||||
## Configuration Options
|
||||
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `storage_dir` | `"transaction_records"` | Directory where transaction records are stored |
|
||||
| `ttl_days` | `3` | Number of days before a transaction record expires |
|
||||
|
||||
## Testing
|
||||
|
||||
This library includes a comprehensive test suite using pytest. To run the tests:
|
||||
|
||||
```bash
|
||||
# Install pytest if you don't have it
|
||||
pip install pytest
|
||||
|
||||
# Run the tests
|
||||
pytest transaction_tracker_tests.py -v
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The library raises specific exceptions that you can catch and handle:
|
||||
|
||||
- `TransactionAlreadyProcessedError`: Raised when attempting to process a transaction that was already processed
|
||||
- `ValueError`: Raised when the transaction ID parameter cannot be found in the function arguments
|
||||
|
||||
## License
|
||||
|
||||
[MIT License](LICENSE)
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
Reference in New Issue
Block a user