-
-
Notifications
You must be signed in to change notification settings - Fork 390
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrations 3.0 #858
Migrations 3.0 #858
Conversation
/** @var AbstractMigration */ | ||
private $migration; | ||
|
||
public function __construct(Version $version, AbstractMigration $migration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am for making the ctor private and a have a static named constructor to be immutable.
Also I am for version() and migration() without the get prefix.
Same should be applied to the other value objects
*/ | ||
public $executionTime; | ||
|
||
public function __construct(Version $version, ?DateTime $executedOn, ?int $executionTime) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ExecutionTime::fromMilliseconds(...) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. . And that method what should do? Just return back the same value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but its self explanatory. Looking at $executionTime
variable name is not helpful, unless it would be named $executionTimeInMs
oder $executionTimeInMilliseconds
.
it could also provide a ExecutionTime->inSeconds()
which could be helpful when outputting it to the user? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you are suggesting is a value object instead of the integer, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
final class ExecutionTime
{
/** var int */
private $time;
private function __construct(int $time)
{
$this->time = $time;
{
public function fromMilliseconds(int $time): self
{
return new self($time);
}
public function toMilliseconds(): int
{
return $time;
}
public function toSeconds(): // int or float here
{
return $time / 1000;
}
}
Something like this, yes and then use it like this:
public function __construct(Version $version, ?DateTime $executedOn, ?ExecutionTime $executionTime)
$this->platform->getDateTimeFormatString(), | ||
$row['executed_on'] | ||
); | ||
$migration = new ExecutedMigration($version, $executedOn, $row['execution_time']? intval($row['execution_time']) : null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here:
$migration = new ExecutedMigration($version, $executedOn, $row['execution_time']? intval($row['execution_time']) : null); | |
$migration = new ExecutedMigration($version, $executedOn, $row['execution_time']? ExecutionTime::fromMilliseconds(intval($row['execution_time'])) : null); |
This is great. Love to see someone tearing this a part more! Can we document the BC breaks and update some of the docs to reflect the changes? I think it would help me understand what has changed so far from the users perspective and would allow me to provide feedback. Let me know when you are ready for a thorough review. |
Sounds great! I have discussed this a bit with @alcaeus , currently I'm spending on this PR 5-8 h/week. I was planning in documenting the changes a bit. As soon as I have something will ping you here! |
Is there a migration plan available for that ? This involves at least 2 things regarding BC:
Also, how will the ordering of migrations work ? Currently, when you have multiple unexecuted migrations, they are applied based on their version using date sorting. But once their version is the FQCN, we need to have a different sorting algorithm, and you don't describe what it is AFAICT. |
For both of this questions have the same solution. This part of code will be responsible for doing that migration. Is not yet coded, but is already on my todo-list.
The current sorting algorithm used in v2 for migrations is |
I don't even see how that's possible. your own migrations will still need interleaving with the dependency migrations, as some of your migrations will have been written before the upgrade of one of the dependencies bring a new migration there. A dependency graph is not the solution here. |
If you have single migrations that depend on other migrations from other
packages, you have to manage it on your own with a custom sorting algorithm.
I doubt that will be possible to find a decent way to sort migrations out
of the box and cover most of the cases, thus custom sorting should allow
users to handle it on their own.
This pr does not propose a way to manage migration dependencies, it just
allows you to sort them in any other you prefer.
Did i miss maybe your point or it explains the problem?
…On Mon, 16 Sep 2019, 17:52 Christophe Coevoet, ***@***.***> wrote:
n an ideal world, composer dependency graph could be used to provide
out-of-the-box advanced sorting, but this is too app-specific and out of
the scope for now.
I don't even see how that's possible. your own migrations will still need
interleaving with the dependency migrations, as some of your migrations
will have been written before the upgrade of one of the dependencies bring
a new migration there. A dependency graph is not the solution here.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#858?email_source=notifications&email_token=AAF5UJ4F7CFJXUNEZO5W5NTQJ6TULA5CNFSM4IWZ62MKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6ZTSIY#issuecomment-531839267>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAF5UJ2X2ZSUDYDGVSCUSVDQJ6TULANCNFSM4IWZ62MA>
.
|
Current status: ~90% of functionalities have been migrated ( I have also migrated most of the tests, wrote some new and deleted a lot of other. This is some critical issue. Since the previous version had 3-4 god classes tightly couples doing most of the job ( My plan in the next days is to restore the test coverage to something around 95%, before that I plan to update the documentation with the user-facing changes. Documenting the code changes is a bit more difficult... what about using https://github.com/Roave/BackwardCompatibilityCheck ? (here the GIST with the changes detected by it) @OskarStark Thanks for the revirews, as soon as I will have a more polished architecture, will start addressing the comments. |
@goetas Sounds like a good plan to me. We also need to at some point look in to how this affects all the 3rd party integrations, like the DoctrineMigrationsBundle for Symfony for example. |
That is on my todo-list (since the project that i'm working on will need the bundle too) |
I've analyzed the current master and this branch with PhpDependencyAnalysis to track dependencies between classes in this doctrine/migrations. The configuration file I've used is: mode: 'usage'
source: './lib'
filePattern: '*.php'
formatter: 'PhpDA\Writer\Strategy\Svg'
target: './complex-cycle.svg'
groupLength: 3
visitorOptions:
PhpDA\Parser\Visitor\Required\DeclaredNamespaceCollector: {minDepth: 2, sliceLength: 6, excludePattern: '/^((?!.*(Doctrine\\Migrations))|(?=.*Exception)).*$/'}
PhpDA\Parser\Visitor\Required\MetaNamespaceCollector: {minDepth: 2, sliceLength: 4, excludePattern: '/^((?!.*(Doctrine\\Migrations))|(?=.*Exception)).*$/'}
PhpDA\Parser\Visitor\Required\UsedNamespaceCollector: {minDepth: 2, sliceLength: 4, excludePattern: '/^((?!.*(Doctrine\\Migrations))|(?=.*Exception)).*$/'} The results are the following https://gist.github.com/goetas/e5ee7546496e673360df5657ec5b38bd . Red line in the graph are circular dependencies between classes. As you can see, in v3 all circular deps are gone. |
Any help? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you need to fix the autoload_directories
in phpstan.neon.dist, as the _regression
folder is gone. That's what's breaking phpstan entirely right now.
lib/Doctrine/Migrations/Configuration/Connection/Loader/ConnectionHelperLoader.php
Outdated
Show resolved
Hide resolved
lib/Doctrine/Migrations/Configuration/Connection/Loader/NoConnectionLoader.php
Outdated
Show resolved
Hide resolved
@@ -65,6 +46,9 @@ public function buildMigrationFile( | |||
|
|||
private function getVersionUpdateQuery(string $version, string $direction) : string | |||
{ | |||
// @todo this is hard to implement since MetadataStorage abstracts the migrations table |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but without this, things are broken as the metadata storage is not updated with executing this file. So this must be solved.
It might mean that the MetadataStorage needs to expose a method returning the needed queries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it make sense then to have metadata storage interface? If it is going to be only one implementation, what about dropping the interface and typehint the concrete implementation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well, the metadata storage interface could have a method returning the queries necessary to update the storage (which may be no queries if the storage cannot be updated in SQL).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But then metadata storage interface will be bound to SQL, having other "storages" will make no sense... right? or in that case the extra method for the queries will just return NULL? )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have discussed this with @alcaeus . This will be covered in a separate PR/ticket and there can be explored a solution for the issue
lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorage.php
Outdated
Show resolved
Hide resolved
lib/Doctrine/Migrations/Metadata/Storage/TableMetadataStorage.php
Outdated
Show resolved
Hide resolved
lib/Doctrine/Migrations/Tools/Console/Command/AbstractCommand.php
Outdated
Show resolved
Hide resolved
Only 111 errors left :-) |
PHPStan 0 errors! 🎉 🎉 🎉 |
…of having a long list
Congratulations 🍾🎉🎊🎈 |
@@ -100,12 +98,12 @@ public function execute( | |||
InputInterface $input, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also change the visibility from "public" to "protected" on the Command class to match the declaration with Symfony/Console ?
If you agree, I may open a PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Did not know was protected
I must say decision to use FQCN instead of version number is causing us issues. We have deployed branch with doctrine/migrations 3.x to our staging environment. It migrated the table. Now other branches with older version of doctrine/migrations fail because they don't recognize versions as executed anymore. For the next time, there should be a BC layer in currently maintained branch which recognizes both formats. |
Summary
This PR proposes what could become doctrine/migrations 3.0. (Some code and ideas are borrowed from #162)
This is a "work in progress", so any feedback is appreciated.
Exiting user-facing features are have been kept as they are ( some BC breaks are present of course).
Summary of changes:
Configuration
,MigrationRepository
andVersion
that were doing all possible kind of things and having circular dependencies between each other )Tests have not been updated, but the provided prototype has most of the features already working.
Rollup and Diff commands have not been updated yet.
I realize that is a huge PR and hard to review, but the configuration and migration-repository class was passed all over the places, and as soon as I started to remove methods from it, each other class had to be changed...
Todo: