Links

DBAL Support

Transactions, Asynchronous, Dead Letter Queue PHP DBAL

Installation

composer require ecotone/dbal

Module Powered By

Powered by powerful database abstraction layer Doctrine/Dbal and Enqueue for asynchronous communication

Configuration

In order to use Dbal Support we need to add ConnectionFactory to our Dependency Container.

Using Existing Connection

Symfony
Laravel
# config/services.yaml
Enqueue\Dbal\DbalConnectionFactory:
factory: ['Ecotone\Dbal\DbalConnection', 'create']
arguments: ["@Doctrine\DBAL\Connection"]
# Register Service in Provider
use Enqueue\Dbal\DbalConnectionFactory;
use Ecotone\Dbal\DbalConnection;
public function register()
{
$this->app->singleton(DbalConnectionFactory::class, function ($app) {
return DbalConnection::create(DB::connection()->getDoctrineConnection());
});
}
We register our DbalConnectionFactory under the class name Enqueue\Dbal\DbalConnectionFactory. This will help Ecotone resolve it automatically, without any additional configuration.
Ecotone starts database transaction by default. Make use of existing connection to be sure your changes are commited.

Using Database Connection String

Symfony
Laravel
Lite
# config/services.yaml
Enqueue\Dbal\DbalConnectionFactory:
class: Enqueue\Dbal\DbalConnectionFactory
factory: ["Ecotone\Dbal\DbalConnection", "fromDsn"]
arguments: ["pgsql://user:password@host:5432/db_name"]
# Register Service in Provider
use Enqueue\Dbal\DbalConnectionFactory;
use Ecotone\Dbal\DbalConnection;
public function register()
{
$this->app->singleton(DbalConnectionFactory::class, function () {
return DbalConnection::fromDsn('pgsql://user:password@host:5432/db_name');
});
}
use Ecotone\Dbal\DbalConnection;
$application = EcotoneLiteApplication::boostrap(
[
DbalConnectionFactory::class => DbalConnection::fromDsn('pgsql://user:password@host:5432/db_name')
]
);

Using Manager Registry

If we want to make use of existing connection using Manager Registry, we can do it this way
Symfony
# config/services.yaml
Enqueue\Dbal\DbalConnectionFactory:
factory: ['Ecotone\Dbal\DbalConnection', 'createForManagerRegistry']
arguments: ["@doctrine","default"]
Register Manager Registry under DbalConnectionFactory, if you want to make use of auto configuration.
Otherwise you will need to tell Message Channel, Transactions the name of Connection Factory.

Enabling ORM Based Aggregates

Configuring Dbal Module with Manager Registry allows to make your Entities work as a Ecotone's Aggregates.
class Configuration
{
#[ServiceContext]
public function enableORMBasedAggregates()
{
return DbalConfiguration::createWithDefaults()
->withDoctrineORMRepositories(true)
}
}
Ecotone will take care of object flush and clearing your object manager. This can be disabled via DbalConfiguration.

Message Channel

To create Dbal Backed Message Channel, we need to create Service Context.
class MessagingConfiguration
{
#[ServiceContext]
public function orderChannel()
{
return DbalBackedMessageChannelBuilder::create("orders");
}
}
Now orders channel will be available in our Messaging System.

Message Channel Configuration

DbalBackedMessageChannelBuilder::create("orders")
->withAutoDeclare(false) // do not auto declare queue
->withDefaultTimeToLive(1000) // limit TTL of messages

Transactions

By default Ecotoneenables transactions for all Asynchronous Endpoints and Command Bus. You may use of Service Context to turn off this configuration. You may also add more connections to be handled.
class DbalConfiguration
{
#[ServiceContext]
public function registerTransactions() : array
{
return [
DbalConfiguration::createWithDefaults()
->withTransactionOnCommandBus(true) // Turn for running command bus
->withTransactionOnAsynchronousEndpoints(true) // for all asynchronous endpoints
->withoutTransactionOnAsynchronousEndpoints(["notifications"]) // turn off for list of asynchronous endpoint
->withDefaultConnectionReferenceNames([
"Enqueue\Dbal\DbalConnectionFactory",
"AnotherDbalConnectionFactory"
])
];
}
}
If we disable global transactions, it make sense to enable transactions on specific endpoint. To do it all we need to do is to mark it with Ecotone\Dbal\DbalTransaction\DbalTransaction attribute.
#[CommandHandler]
#[DbalTransaction]
public function sellProduct(SellProduct $command) : void
{
// do something with $command
}

Document Store

DBAL provides support for Document Store, which is enabled by default. Every document is stored inside the "ecotone_document_store" table.

Standard Aggregate Repository

You may enable support for storing standard aggregates.
#[ServiceContext]
public function getDbalConfiguration(): DbalConfiguration
{
return DbalConfiguration::createWithDefaults()
->withDocumentStore(enableDocumentStoreAggregateRepository: true);
}

In Memory Document Store

For testing purposes you may want to enable In Memory implementation.
#[ServiceContext]
public function configuration()
{
return DbalConfiguration::createWithDefaults()
->withDocumentStore(inMemoryDocumentStore: true);
}

Table initialization

Table will be create for you, however this comes with extra SQL cost, to verify before adding new document, if table exists. After releasing you may want to disable the check, as you know, that the table already exists.
#[ServiceContext]
public function getDbalConfiguration(): DbalConfiguration
{
return DbalConfiguration::createWithDefaults()
->withDocumentStore(initializeDatabaseTable: false);
}