Skip to content

Commit

Permalink
refactor(reset database): add dama decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil committed Aug 25, 2024
1 parent bad09af commit a29c898
Show file tree
Hide file tree
Showing 14 changed files with 180 additions and 232 deletions.
24 changes: 22 additions & 2 deletions config/orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver;
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;
use Zenstruck\Foundry\ORM\OrmDatabaseResetter;
use Zenstruck\Foundry\ORM\OrmSchemaResetter;
use Zenstruck\Foundry\ORM\OrmV2PersistenceStrategy;
use Zenstruck\Foundry\ORM\OrmV3PersistenceStrategy;
use Zenstruck\Foundry\ORM\ResetDatabase\DamaDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\DamaSchemaResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\OrmDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\OrmSchemaResetter;

return static function (ContainerConfigurator $container): void {
$container->services()
Expand All @@ -31,4 +34,21 @@
])
->tag('.foundry.persistence.schema_resetter')
;

if (\class_exists(StaticDriver::class)) {
$container->services()
->set('.zenstruck_foundry.persistence.database_resetter.orm.dama', DamaDatabaseResetter::class)
->decorate('.zenstruck_foundry.persistence.database_resetter.orm')
->args([
service('.inner'),
])
->tag('.foundry.persistence.database_resetter')
->set('.zenstruck_foundry.persistence.schema_resetter.orm.dama', DamaSchemaResetter::class)
->decorate('.zenstruck_foundry.persistence.schema_resetter.orm')
->args([
service('.inner'),
])
->tag('.foundry.persistence.schema_resetter')
;
}
};
5 changes: 5 additions & 0 deletions config/persistence.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
namespace Symfony\Component\DependencyInjection\Loader\Configurator;

use Zenstruck\Foundry\Persistence\PersistenceManager;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseManager;

return static function (ContainerConfigurator $container): void {
$container->services()
->set('.zenstruck_foundry.persistence_manager', PersistenceManager::class)
->args([
tagged_iterator('.foundry.persistence_strategy'),
service('.zenstruck_foundry.persistence.reset_database_manager'),
])
->set('.zenstruck_foundry.persistence.reset_database_manager', ResetDatabaseManager::class)
->args([
tagged_iterator('.foundry.persistence.database_resetter'),
tagged_iterator('.foundry.persistence.schema_resetter'),
])
Expand Down
3 changes: 3 additions & 0 deletions src/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public function __construct(
$this->instantiator = $instantiator;
}

/**
* @throws PersistenceNotAvailable
*/
public function persistence(): PersistenceManager
{
return $this->persistence ?? throw new PersistenceNotAvailable('No persistence managers configured. Note: persistence cannot be used in unit tests.');
Expand Down
39 changes: 0 additions & 39 deletions src/Mongo/MongoPersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,43 +89,4 @@ public function isEmbeddable(object $object): bool
{
return $this->objectManagerFor($object::class)->getClassMetadata($object::class)->isEmbeddedDocument;
}

public function resetDatabase(KernelInterface $kernel): void
{
// noop
}

public function resetSchema(KernelInterface $kernel): void
{
$application = self::application($kernel);

foreach ($this->managers() as $manager) {
try {
self::runCommand(
$application,
'doctrine:mongodb:schema:drop',
[
'--dm' => $manager,
]
);
} catch (\Exception) {
}

self::runCommand(
$application,
'doctrine:mongodb:schema:create',
[
'--dm' => $manager,
]
);
}
}

/**
* @return string[]
*/
private function managers(): array
{
return $this->config['reset']['document_managers'];
}
}
106 changes: 1 addition & 105 deletions src/ORM/AbstractORMPersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Persistence\PersistenceManager;
use Zenstruck\Foundry\Persistence\PersistenceStrategy;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseHandler;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseManager;

/**
* @author Kevin Bond <kevinbond@gmail.com>
Expand Down Expand Up @@ -87,27 +87,6 @@ final public function isEmbeddable(object $object): bool
return $this->objectManagerFor($object::class)->getClassMetadata($object::class)->isEmbeddedClass;
}

final public function resetDatabase(KernelInterface $kernel): void
{
$application = self::application($kernel);

$this->dropAndResetDatabase($application);
$this->createSchema($application);
}

final public function resetSchema(KernelInterface $kernel): void
{
if (ResetDatabaseHandler::isDAMADoctrineTestBundleEnabled()) {
// not required as the DAMADoctrineTestBundle wraps each test in a transaction
return;
}

$application = self::application($kernel);

$this->dropSchema($application);
$this->createSchema($application);
}

final public function managedNamespaces(): array
{
$namespaces = [];
Expand All @@ -118,87 +97,4 @@ final public function managedNamespaces(): array

return \array_values(\array_merge(...$namespaces));
}

private function dropAndResetDatabase(Application $application): void
{
foreach ($this->connections() as $connection) {
$databasePlatform = $this->registry->getConnection($connection)->getDatabasePlatform(); // @phpstan-ignore-line

if ($databasePlatform instanceof SQLitePlatform) {
// we don't need to create the sqlite database - it's created when the schema is created
continue;
}

if ($databasePlatform instanceof PostgreSQLPlatform) {
// let's drop all connections to the database to be able to drop it
self::runCommand(
$application,
'dbal:run-sql',
[
'--connection' => $connection,
'sql' => 'SELECT pid, pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = current_database() AND pid <> pg_backend_pid()',
],
canFail: true,
);
}

self::runCommand($application, 'doctrine:database:drop', [
'--connection' => $connection,
'--force' => true,
'--if-exists' => true,
]);
self::runCommand($application, 'doctrine:database:create', ['--connection' => $connection]);
}
}

private function createSchema(Application $application): void
{
if (self::RESET_MODE_MIGRATE === $this->config['reset']['mode']) {
self::runCommand($application, 'doctrine:migrations:migrate', [
'--no-interaction' => true,
]);

return;
}

foreach ($this->managers() as $manager) {
self::runCommand($application, 'doctrine:schema:update', [
'--em' => $manager,
'--force' => true,
]);
}
}

private function dropSchema(Application $application): void
{
if (self::RESET_MODE_MIGRATE === $this->config['reset']['mode']) {
$this->dropAndResetDatabase($application);

return;
}

foreach ($this->managers() as $manager) {
self::runCommand($application, 'doctrine:schema:drop', [
'--em' => $manager,
'--force' => true,
'--full-database' => true,
]);
}
}

/**
* @return string[]
*/
private function managers(): array
{
return $this->config['reset']['entity_managers'];
}

/**
* @return string[]
*/
private function connections(): array
{
return $this->config['reset']['connections'];
}
}
52 changes: 52 additions & 0 deletions src/ORM/ResetDatabase/DamaDatabaseResetter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM\ResetDatabase;

use DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver;
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Configuration;
use Zenstruck\Foundry\Persistence\PersistenceManager;
use Zenstruck\Foundry\Persistence\ResetDatabase\DatabaseResetterInterface;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseManager;

/**
* @internal
* @author Nicolas PHILIPPE <nikophil@gmail.com>
*/
final class DamaDatabaseResetter implements DatabaseResetterInterface
{
public function __construct(
private DatabaseResetterInterface $decorated,
) {
}

public function resetDatabase(KernelInterface $kernel): void
{
$isDAMADoctrineTestBundleEnabled = ResetDatabaseManager::isDAMADoctrineTestBundleEnabled();

if (!$isDAMADoctrineTestBundleEnabled) {
$this->decorated->resetDatabase($kernel);

return;
}

// disable static connections for this operation
StaticDriver::setKeepStaticConnections(false);

$this->decorated->resetDatabase($kernel);

if (PersistenceManager::isOrmOnly()) {
// add global stories so they are available after transaction rollback
Configuration::instance()->stories->loadGlobalStories();
}

// shutdown kernel before re-enabling static connections
// this would prevent any error if some ResetInterface execute some queries (example: symfony/doctrine-messenger)
$kernel->shutdown();

// re-enable static connections
StaticDriver::setKeepStaticConnections(true);
}
}
31 changes: 31 additions & 0 deletions src/ORM/ResetDatabase/DamaSchemaResetter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseManager;
use Zenstruck\Foundry\Persistence\ResetDatabase\SchemaResetterInterface;

/**
* @internal
* @author Nicolas PHILIPPE <nikophil@gmail.com>
*/
final class DamaSchemaResetter implements SchemaResetterInterface
{
public function __construct(
private SchemaResetterInterface $decorated,
) {
}

public function resetSchema(KernelInterface $kernel): void
{
if (ResetDatabaseManager::isDAMADoctrineTestBundleEnabled()) {
// not required as the DAMADoctrineTestBundle wraps each test in a transaction
return;
}

$this->decorated->resetSchema($kernel);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM;
namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpKernel\KernelInterface;
Expand Down Expand Up @@ -42,11 +42,17 @@ private function registry(): ManagerRegistry
return $this->registry;
}

/**
* @return list<string>
*/
private function managers(): array
{
return $this->managers;
}

/**
* @return list<string>
*/
private function connections(): array
{
return $this->connections;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM;
namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
Expand Down Expand Up @@ -43,6 +43,7 @@ private function dropAndResetDatabase(Application $application): void
'--force' => true,
'--if-exists' => true,
]);

self::runCommand($application, 'doctrine:database:create', ['--connection' => $connection]);
}
}
Expand Down
Loading

0 comments on commit a29c898

Please sign in to comment.