aeatech / transaction-manager-bundle
Symfony bundle that glues AEATech Transaction Manager into the Symfony ecosystem, providing Doctrine DBAL integration, multiple transaction managers.
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
Type:symfony-bundle
pkg:composer/aeatech/transaction-manager-bundle
Requires
- php: >=8.2
- ext-pdo: *
- aeatech/transaction-manager-core: ^1.0
- symfony/config: ^6.4.15 || ^7.0
- symfony/dependency-injection: ^6.4.15 || ^7.0
- symfony/framework-bundle: ^6.4.15 || ^7.0
- symfony/yaml: ^6.4.15 || ^7.0
Requires (Dev)
- aeatech/transaction-manager-doctrine-adapter: ^1.0
- aeatech/transaction-manager-mysql: ^1.0
- aeatech/transaction-manager-postgresql: ^1.0
- mockery/mockery: ^1.6.10
- phpstan/phpstan: ^2.1
- phpstan/phpstan-mockery: ^2.0
- phpunit/phpunit: ^11.5
- roave/security-advisories: dev-master
- symfony/error-handler: ^6.4.15 || ^7.0
- symfony/http-kernel: ^6.4.15 || ^7.0
Suggests
- aeatech/transaction-manager-doctrine-adapter: Required to use the "connection_adapter: doctrine" configuration (Doctrine DBAL integration).
- aeatech/transaction-manager-mysql: Provides MySQL-specific error heuristics and SQL dialect support.
- aeatech/transaction-manager-postgresql: Provides PostgreSQL-specific error heuristics and SQL dialect support.
This package is not auto-updated.
Last update: 2026-01-12 10:54:34 UTC
README
Symfony bundle that integrates AEATech Transaction Manager into the Symfony ecosystem.
Features
- Multiple Transaction Managers: Configure different managers for different database connections.
- Doctrine DBAL Integration: Out-of-the-box support for Doctrine connections via
aeatech/transaction-manager-doctrine-adapter. - Platform-Specific Factories: Convenient interfaces for creating MySQL and PostgreSQL transactions.
- Advanced Retry Policies: Customizable exponential backoff strategies with jitter.
- PHP Attributes Support: Easy autoconfiguration for custom heuristics, classifiers, and adapters.
- Lazy Loading: Managers are initialized only when first accessed via a service locator.
Table of Contents
Prerequisites
- PHP 8.2 or higher
- Symfony 6.4 or 7.x
Installation
composer require aeatech/transaction-manager-bundle
Depending on your database, you also need to install the corresponding driver package:
For MySQL
composer require aeatech/transaction-manager-mysql
For PostgreSQL
composer require aeatech/transaction-manager-postgresql
For Doctrine DBAL (Adapter)
composer require aeatech/transaction-manager-doctrine-adapter
Configuration
The bundle allows you to configure multiple transaction managers, each with its own platform and connection.
YAML Configuration
# config/packages/aea_tech_transaction_manager.yaml aea_tech_transaction_manager: default_manager: main managers: main: platform: mysql connection_adapter: doctrine: connection: default # Connection name from doctrine.yaml retry_policy: max_retries: 5 # Default: 7 backoff: base_delay_ms: 100 # Default: 150 max_delay_ms: 5000 # Default: 2000 multiplier: 2.0 # Default: 2.0 jitter_ms: 100 # Default: 250 analytics: platform: postgres connection_adapter: 'App\PostgresCustomConnectionAdapter' execution_plan_builder: deferred_build_resolver: strategy: caching # Options: "caching" (default) or "reflection" error_classifier: heuristics: 'App\PostgresCustomHeuristics' retry_policy: max_retries: 3 backoff: 'App\PostgresCustomBackoff'
Configuration Options
- Connection Adapter:
doctrine: Requiresaeatech/transaction-manager-doctrine-adapter. Specify the connection name.service: Provide a service ID implementingConnectionInterface.
- Execution Plan Builder:
deferred_build_resolver.strategy: How to detect transactions that need deferred building.deferred_build_resolver.service: Custom service ID implementingDeferredBuildResolverInterface.
- Error Classifier:
service: Custom service ID implementingErrorClassifierInterface.heuristics: Custom service ID implementingDatabaseErrorHeuristicsInterface.
Autoconfiguration with PHP Attributes
The bundle provides PHP attributes to configure certain services automatically without modifying the YAML configuration. This is the recommended way for most use cases.
Note: If you configure a component (like heuristics or a classifier) for a manager both in YAML and via an attribute, an
InvalidConfigurationExceptionwill be thrown.
Available Attributes
All attributes accept a managerNames parameter (string or array of strings).
| Attribute | Interface | Description |
|---|---|---|
#[AsHeuristics] |
DatabaseErrorHeuristicsInterface |
Overrides platform-specific error heuristics. |
#[AsErrorClassifier] |
ErrorClassifierInterface |
Provides custom error classification logic. |
#[AsDeferredBuildResolver] |
DeferredBuildResolverInterface |
Customizes how deferred builds are detected. |
#[AsConnectionAdapter] |
ConnectionInterface |
Provides a custom database connection adapter. |
#[AsRetryPolicyBackoff] |
BackoffStrategyInterface |
Implements a custom retry backoff strategy. |
Example:
use AEATech\TransactionManager\DatabaseErrorHeuristicsInterface; use AEATech\TransactionManagerBundle\Attribute\AsHeuristics; #[AsHeuristics(managerNames: 'main')] class MyCustomHeuristics implements DatabaseErrorHeuristicsInterface { public function isConnectionIssue(?string $sqlState, ?int $driverCode, string $message): bool { // your logic } public function isTransientIssue(?string $sqlState, ?int $driverCode, string $message): bool { // your logic } }
Usage
Basic Example
The main way to interact with the bundle is through the TransactionManagerInterface and platform-specific factories.
use AEATech\TransactionManager\TransactionManagerInterface; use AEATech\TransactionManager\MySQL\MySQLTransactionsFactoryInterface; class RegisterUserService { public function __construct( private TransactionManagerInterface $tm, private MySQLTransactionsFactoryInterface $factory ) {} public function register(string $email): void { // Create a transaction (this doesn't execute anything yet) $tx = $this->factory->createInsert('users', ['email' => $email]); // Run the transaction (includes retries on transient errors) $this->tm->run($tx); } }
Autowiring
Default Manager
public function __construct(TransactionManagerInterface $tm) { // Injects the manager configured in 'default_manager' }
Specific Manager
use Symfony\Component\DependencyInjection\Attribute\Autowire; public function __construct( #[Autowire(service: 'aea_tech_transaction_manager.analytics')] TransactionManagerInterface $analyticsTm ) {}
Transaction Factories
The bundle automatically creates aliases for platform-specific transaction factories for the default manager's platform.
use AEATech\TransactionManager\MySQL\MySQLTransactionsFactoryInterface; public function __construct(MySQLTransactionsFactoryInterface $factory) { /* ... */ }
Using Transaction Manager Registry
If you need to select a manager at runtime (e.g., in a worker or for multi-tenant applications), use TransactionManagerRegistryInterface.
use AEATech\TransactionManagerBundle\TransactionManagerRegistryInterface; class MaintenanceCommand { public function __construct(private TransactionManagerRegistryInterface $registry) {} public function execute(): void { // Get a specific manager by name $tm = $this->registry->getManager('analytics'); // Get all registered manager names $names = $this->registry->getManagerNames(); // Get the default manager name $default = $this->registry->getDefaultManagerName(); } }
Testing
When writing unit tests for your services, you should mock TransactionManagerInterface.
Using Mockery:
public function testRegister(): void { $tm = \Mockery::mock(TransactionManagerInterface::class); $factory = \Mockery::mock(MySQLTransactionsFactoryInterface::class); $tx = \Mockery::mock(\AEATech\TransactionManager\TransactionInterface::class); $factory->shouldReceive('createInsert')->andReturn($tx); // Expect the transaction to be run $tm->shouldReceive('run')->with($tx)->once(); $service = new RegisterUserService($tm, $factory); $service->register('test@example.com'); }
Development
Start the Environment
docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml up -d --build
Install Dependencies
docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml exec php-cli-8.2 composer install
Run Tests
# Run tests for all supported PHP versions for v in 8.2 8.3 8.4; do \ echo "Testing PHP $v..."; \ docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml exec php-cli-$v vendor/bin/phpunit || break; \ done
# PHP 8.4 docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml exec php-cli-8.4 vendor/bin/phpunit
PHPStan
docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml exec php-cli-8.4 vendor/bin/phpstan analyse -c phpstan.neon --memory-limit=1G
Stop the Environment
docker-compose -p aeatech-transaction-manager-bundle -f docker/docker-compose.yml down -v
License
This project is licensed under the MIT License. See the LICENSE file for details.