Skip to content

Commit

Permalink
refactor(reset database): enable migration mode
Browse files Browse the repository at this point in the history
  • Loading branch information
nikophil committed Oct 22, 2024
1 parent 91ac05d commit a3b11ac
Show file tree
Hide file tree
Showing 21 changed files with 263 additions and 310 deletions.
43 changes: 22 additions & 21 deletions config/orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
use Zenstruck\Foundry\ORM\DoctrineOrmVersionGuesser;
use Zenstruck\Foundry\ORM\OrmV2PersistenceStrategy;
use Zenstruck\Foundry\ORM\OrmV3PersistenceStrategy;
use Zenstruck\Foundry\ORM\ResetDatabase\AbstractOrmResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\DamaDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\DamaSchemaResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\OrmDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\OrmSchemaResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\SchemaDatabaseResetter;
use Zenstruck\Foundry\ORM\ResetDatabase\MigrateDatabaseResetter;

return static function (ContainerConfigurator $container): void {
$container->services()
Expand All @@ -19,36 +19,37 @@
abstract_arg('config'),
])
->tag('.foundry.persistence_strategy')
->set('.zenstruck_foundry.persistence.database_resetter.orm', OrmDatabaseResetter::class)
->args([
service('doctrine'),
abstract_arg('managers'),
abstract_arg('connections'),
])

->set('.zenstruck_foundry.persistence.database_resetter.orm.abstract', AbstractOrmResetter::class)
->arg('$registry', service('doctrine'))
->arg('$managers', service('managers'))
->arg('$connections', service('connections'))
->abstract()

->set('.zenstruck_foundry.persistence.database_resetter.orm.schema', SchemaDatabaseResetter::class)
->parent('.zenstruck_foundry.persistence.database_resetter.orm.abstract')
->tag('.foundry.persistence.database_resetter')
->tag('.foundry.persistence.schema_resetter')

->set('.zenstruck_foundry.persistence.database_resetter.orm.migrate', MigrateDatabaseResetter::class)
->arg('$configurations', abstract_arg('configurations'))
->parent('.zenstruck_foundry.persistence.database_resetter.orm.abstract')
->tag('.foundry.persistence.database_resetter')
->set('.zenstruck_foundry.persistence.schema_resetter.orm', OrmSchemaResetter::class)
->args([
service('doctrine'),
abstract_arg('managers'),
abstract_arg('connections'),
])
->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')
->set('.zenstruck_foundry.persistence.database_resetter.orm.schema.dama', DamaDatabaseResetter::class)
->decorate('.zenstruck_foundry.persistence.database_resetter.orm.schema')
->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')
->set('.zenstruck_foundry.persistence.database_resetter.orm.migrate.dama', DamaDatabaseResetter::class)
->decorate('.zenstruck_foundry.persistence.database_resetter.orm.migrate')
->args([
service('.inner'),
])
->tag('.foundry.persistence.schema_resetter')
;
}
};
20 changes: 4 additions & 16 deletions src/Mongo/MongoSchemaResetter.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
namespace Zenstruck\Foundry\Mongo;

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

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class MongoSchemaResetter implements SchemaResetterInterface
final class MongoSchemaResetter implements SchemaResetter
{
use SymfonyCommandRunner;

Expand All @@ -29,23 +29,11 @@ public function resetSchema(KernelInterface $kernel): void

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

self::runCommand(
$application,
'doctrine:mongodb:schema:create',
[
'--dm' => $manager,
]
);
self::runCommand($application, 'doctrine:mongodb:schema:create', ['--dm' => $manager]);
}
}
}
11 changes: 1 addition & 10 deletions src/ORM/AbstractORMPersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,10 @@

namespace Zenstruck\Foundry\ORM;

use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\MappingException as ORMMappingException;
use Doctrine\Persistence\Mapping\MappingException;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Persistence\PersistenceManager;
use Zenstruck\Foundry\Persistence\PersistenceStrategy;
use Zenstruck\Foundry\Persistence\ResetDatabase\ResetDatabaseManager;

/**
* @author Kevin Bond <[email protected]>
Expand All @@ -32,9 +26,6 @@
*/
abstract class AbstractORMPersistenceStrategy extends PersistenceStrategy
{
public const RESET_MODE_SCHEMA = 'schema';
public const RESET_MODE_MIGRATE = 'migrate';

final public function contains(object $object): bool
{
$em = $this->objectManagerFor($object::class);
Expand All @@ -53,7 +44,7 @@ final public function hasChanges(object $object): bool
// cannot use UOW::recomputeSingleEntityChangeSet() here as it wrongly computes embedded objects as changed
$em->getUnitOfWork()->computeChangeSet($em->getClassMetadata($object::class), $object);

return (bool) $em->getUnitOfWork()->getEntityChangeSet($object);
return (bool)$em->getUnitOfWork()->getEntityChangeSet($object);
}

final public function truncate(string $class): void
Expand Down
66 changes: 66 additions & 0 deletions src/ORM/ResetDatabase/AbstractOrmResetter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
use Doctrine\DBAL\Platforms\SQLitePlatform;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Zenstruck\Foundry\Persistence\SymfonyCommandRunner;

/**
* @author Nicolas PHILIPPE <[email protected]>
*/
abstract class AbstractOrmResetter
{
use SymfonyCommandRunner;

/**
* @param list<string> $managers
* @param list<string> $connections
*/
public function __construct(
private readonly Registry $registry,
protected readonly array $managers,
protected readonly array $connections,
) {
}

protected function dropAndResetDatabase(Application $application): void
{
foreach ($this->connections as $connectionName) {
/** @var Connection $connection */
$connection = $this->registry->getConnection($connectionName);
$databasePlatform = $connection->getDatabasePlatform();

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' => $connectionName,
'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' => $connectionName, '--force' => true, '--if-exists' => true]
);

self::runCommand($application, 'doctrine:database:create', ['--connection' => $connectionName]);
}
}
}
15 changes: 12 additions & 3 deletions src/ORM/ResetDatabase/DamaDatabaseResetter.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@
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 <[email protected]>
*/
final class DamaDatabaseResetter implements DatabaseResetterInterface
final class DamaDatabaseResetter implements OrmDatabaseResetter
{
public function __construct(
private DatabaseResetterInterface $decorated,
private OrmDatabaseResetter $decorated,
) {
}

Expand Down Expand Up @@ -49,4 +48,14 @@ public function resetDatabase(KernelInterface $kernel): void
// re-enable static connections
StaticDriver::setKeepStaticConnections(true);
}

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);
}
}
31 changes: 0 additions & 31 deletions src/ORM/ResetDatabase/DamaSchemaResetter.php

This file was deleted.

55 changes: 55 additions & 0 deletions src/ORM/ResetDatabase/MigrateDatabaseResetter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

declare(strict_types=1);

namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Component\HttpKernel\KernelInterface;

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class MigrateDatabaseResetter extends AbstractOrmResetter implements OrmDatabaseResetter
{
/**
* @param list<string> $configurations
*/
public function __construct(
private readonly array $configurations,
Registry $registry,
array $managers,
array $connections,
)
{
parent::__construct($registry, $managers, $connections);
}

final public function resetSchema(KernelInterface $kernel): void
{
$this->resetWithMigration($kernel);
}

public function resetDatabase(KernelInterface $kernel): void
{
$this->resetWithMigration($kernel);
}

private function resetWithMigration(KernelInterface $kernel): void
{
$application = self::application($kernel);

$this->dropAndResetDatabase($application);

if (!$this->configurations) {
self::runCommand($application, 'doctrine:migrations:migrate');

return;
}

foreach ($this->configurations as $configuration) {
self::runCommand($application, 'doctrine:migrations:migrate', ['--configuration' => $configuration]);
}
}
}
54 changes: 3 additions & 51 deletions src/ORM/ResetDatabase/OrmDatabaseResetter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,9 @@

namespace Zenstruck\Foundry\ORM\ResetDatabase;

use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\HttpKernel\KernelInterface;
use Zenstruck\Foundry\Persistence\ResetDatabase\DatabaseResetterInterface;
use Zenstruck\Foundry\Persistence\SymfonyCommandRunner;
use Zenstruck\Foundry\Persistence\ResetDatabase\DatabaseResetter;
use Zenstruck\Foundry\Persistence\ResetDatabase\SchemaResetter;

/**
* @internal
* @author Nicolas PHILIPPE <[email protected]>
*/
final class OrmDatabaseResetter implements DatabaseResetterInterface
interface OrmDatabaseResetter extends DatabaseResetter, SchemaResetter
{
use OrmDatabaseResetterTrait;
use SymfonyCommandRunner;

/**
* @param list<string> $managers
* @param list<string> $connections
*/
public function __construct(
private ManagerRegistry $registry,
private array $managers,
private array $connections,
) {
}

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

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

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;
}
}
Loading

0 comments on commit a3b11ac

Please sign in to comment.