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

1.0.0 2026-01-11 12:22 UTC

This package is not auto-updated.

Last update: 2026-01-12 10:54:34 UTC


README

Code Coverage

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: Requires aeatech/transaction-manager-doctrine-adapter. Specify the connection name.
    • service: Provide a service ID implementing ConnectionInterface.
  • Execution Plan Builder:
    • deferred_build_resolver.strategy: How to detect transactions that need deferred building.
    • deferred_build_resolver.service: Custom service ID implementing DeferredBuildResolverInterface.
  • Error Classifier:
    • service: Custom service ID implementing ErrorClassifierInterface.
    • heuristics: Custom service ID implementing DatabaseErrorHeuristicsInterface.

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 InvalidConfigurationException will 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.