aeatech/transaction-manager-postgresql
Installation
composer require aeatech/transaction-manager-postgresql
Ensure your config/database.php is configured for PostgreSQL.
Basic Setup
Publish the config file (if available) and register the service provider in config/app.php:
'providers' => [
// ...
Aeatech\TransactionManagerPostgresql\TransactionManagerPostgresqlServiceProvider::class,
],
First Use Case Use the transaction manager to wrap a database operation:
use Aeatech\TransactionManagerPostgresql\TransactionManager;
$manager = app(TransactionManager::class);
$manager->transaction(function () {
DB::table('users')->where('id', 1)->update(['name' => 'John Doe']);
DB::table('posts')->where('user_id', 1)->delete();
});
Basic Transactions
Use the transaction() method to group database operations into a single transaction:
$manager->transaction(function () {
// Multiple DB operations here
});
Nested Transactions
The package supports nested transactions (if PostgreSQL's SAVEPOINT is utilized):
$manager->transaction(function () {
DB::table('users')->update(['active' => false]);
$manager->transaction(function () {
DB::table('logs')->insert(['message' => 'Nested operation']);
});
});
Custom Isolation Levels
Specify transaction isolation levels (e.g., READ_COMMITTED, SERIALIZABLE):
$manager->transaction(function () {
// ...
}, 'SERIALIZABLE');
Retry Logic Implement retry logic for transient failures:
$manager->transaction(function () {
// Retry on deadlock
DB::retrying(3, function () {
DB::table('accounts')->update(['balance' => 100]);
});
});
$manager->transaction(function () {
event(new UserUpdated($user));
});
$manager->transaction(function () {
$user = User::find(1);
$user->posts()->delete();
});
$manager->transaction(function () {
User::find(1)->update(['status' => 'pending']);
SendEmailJob::dispatch($user);
});
Connection Leaks Ensure the transaction manager uses the correct database connection. Explicitly bind the connection if needed:
$manager->setConnection('pgsql_secondary');
Nested Transaction Limitations PostgreSQL does not natively support nested transactions (only savepoints). Verify behavior with complex nesting.
Long-Running Transactions
Avoid holding transactions open for extended periods to prevent lock contention. Use commit() or rollback() explicitly if needed.
Error Handling Uncaught exceptions will auto-rollback. Use try-catch for granular control:
try {
$manager->transaction(function () {
// Risky operation
});
} catch (\Exception $e) {
// Log or handle manually
}
postgresql.conf to trace transaction behavior:
log_statement = 'all'
log_min_duration_statement = 0
pg_stat_activity to identify blocked transactions:
SELECT * FROM pg_stat_activity WHERE state = 'active';
Custom Transaction Handlers
Extend the base TransactionManager class to add pre/post hooks:
class CustomTransactionManager extends TransactionManager {
protected function beforeTransaction() {
// Custom logic
}
}
Transaction Metadata Attach metadata (e.g., user ID, context) to transactions for auditing:
$manager->transaction(function () {
// ...
}, 'SERIALIZABLE', ['user_id' => auth()->id()]);
Fallback Mechanisms Implement fallback logic for non-PostgreSQL environments (e.g., MySQL):
if (config('database.default') !== 'pgsql') {
DB::beginTransaction();
// ...
DB::commit();
}
How can I help you explore Laravel packages today?