Skip to content

ownCloud migrations#27041

Merged
DeepDiver1975 merged 7 commits into
masterfrom
owncloud-migrations
Feb 1, 2017
Merged

ownCloud migrations#27041
DeepDiver1975 merged 7 commits into
masterfrom
owncloud-migrations

Conversation

@DeepDiver1975

Copy link
Copy Markdown
Member

Description

Own migration mechanism - doctrine/migration cannot be used due to license issues

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@DeepDiver1975 DeepDiver1975 added this to the 10.0 milestone Jan 26, 2017
@DeepDiver1975 DeepDiver1975 self-assigned this Jan 26, 2017
@DeepDiver1975 DeepDiver1975 force-pushed the owncloud-migrations branch 3 times, most recently from 85e2980 to ef4213d Compare January 26, 2017 14:15

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

upgradeSchema ? (unless you remove down)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

down is off the plate - only up - I'm open regarding the naming of this method

@PVince81

Copy link
Copy Markdown
Contributor

@DeepDiver1975 ready for review or still developing ?

@DeepDiver1975

Copy link
Copy Markdown
Member Author

@DeepDiver1975 ready for review or still developing ?

Unit testing is to be added - but generally speaking this is ready to be reviewed

@DeepDiver1975 DeepDiver1975 changed the title [WIP] Owncloud migrations ownCloud migrations Jan 30, 2017

@PVince81 PVince81 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Look good so far, see my comments for some point needing discussion.

From what I see there is a lot of complexity there so it's very important to have good unit tests here.

$this->addArgument('app', InputArgument::REQUIRED, 'Name of the app this migration command shall work on');
$this
->setName('migrations:execute')
->setDescription('Execute a single migration version up or down manually.')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we limit this to "up" for now to avoid false hopes from admins who might try "down" out ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copy paste issue - we only support up

/**
* Auto-generated migration step: Please modify to your needs!
*/
class Version<version> implements ISqlMigration {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three different migration types ? Is that really needed ? ("keep it simple")

What is the best practice for an app that needs to do Schema and non-Schema migrations (ex: moving stuff inside the data folder). To make it atomic in some way I think a dev would rather write a single generic migration that does all at once: SQL changes, data folder changes, etc all within the run() function.

What do you think ? (to be documented)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So basically I see these three because of the different scenarios

  • change the schema
  • in some cases changing the schema is not enough - we need to explicitly apply sql statements
  • last but not least: I want to allow us to basically write repair steps as migrations as well

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case a single type could be enough, and receive the SQL connection and the Schema injected in the run() method. This way it is possible to do all three within a single one.

Having interfaces for each type sounds a bit over-engineered. There is also the risk of people implementing all three interfaces on a single migration. Would everything still work fine ?

But maybe you had other good reasons in mind ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doing all in run by the implementor of the step requires him/her to do all on his/her own.

Schema migration:

function run($connection) {
    $fromSchema = $connection->createSchema();
    // now do all the schema manipultation

    try {
        $connection->migrateToSchema($toSchema);
    } catch ($ex){
    }
}

I want to take away this from the implementor - all which is to be implemented: changes to the schema - done.

Furthermore - the migration interfaces are designed to execute any operations after the method returns back to core - which allows us to gain more control over the execution.

This have been the ideas while designing these interfaces.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, fine by me.

I could imagine complex situations where it is not possible:

  1. do a DB update
  2. do a FS update
  3. do another DB update based on the FS changes

But for such complex changes one can simply use the generic runner.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well - do 3 steps which are executed one after the other

$numNewMigrations = count(array_diff(array_keys($availableMigrations), $executedMigrations));

$infos = [
'App' => $configuration->getApp(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wild indent

return addcslashes($param, '\\_%');
}

public function createSchema() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPDoc, especially considering the MDB2 part

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be on interface level - will take care

// set default table creation options
$connectionParams['defaultTableOptions'] = [
'collate' => 'utf8_bin',
'tablePrefix' => $connectionParams['tablePrefix']

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we missed this all these years ? Could this save a bit of work from the custom query builder ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea - we shall have a look ...

Comment thread lib/private/DB/MigrationService.php Outdated
// read known migrations
$toBeExecuted = $migrationConfiguration->getMigrationsToExecute($to);
foreach ($toBeExecuted as $version => $class) {
$this->executeStep($migrationConfiguration, $version, $class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how / where are exceptions handled in case an exception is thrown within a step ?
does PHPDoc need an additional @throws clause to clarify this ?

when you add unit tests please also make sure to cover exception handling/forwarding.

Comment thread lib/private/DB/MigrationService.php Outdated
$migrationConfiguration->setOutputWriter(new OutputWriter(function ($message){
\OCP\Util::writeLog('migrations', $message, \OCP\Util::INFO);
}));
public function executeStep(MigrationConfiguration $migrationConfiguration, $version, $class = null) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPDoc

@@ -42,14 +42,10 @@

class Migrator {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, what's a Migrator compared to MigrationService and MigrationConfiguration ? Add PHPDoc to clarify

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migrator: old
MigrService and MigConfig: new

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deprecated ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the migrators are still used for anything which is xml related - I'd keep them for now

use OCP\ILogger;
use OCP\Migration\IOutput;

class SimpleOutput implements IOutput {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this and why do we need this specifically for migrations ? Add answer in PHPDoc

Comment thread lib/public/IDBConnection.php Outdated
* Create the schema of the connected database
*
* @return Schema
* @since 10.0.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10.0

We don't add APIs in minor/patch versions

@DeepDiver1975 DeepDiver1975 force-pushed the owncloud-migrations branch 2 times, most recently from d7fd46f to 5623297 Compare January 30, 2017 22:14
@CLAassistant

CLAassistant commented Jan 30, 2017

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission, we really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
2 out of 3 committers have signed the CLA.

✅ PVince81
✅ DeepDiver1975
❌ scrutinizer-auto-fixer

@PVince81 PVince81 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more minor comments.

Else it looks good.


}

private function generateMigration(MigrationService $ms, $version, $kind) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's a private function, but I miss PHPDoc to explain the format of $version and $kind which are not self-explanatory.


$infos = $this->getMigrationsInfos($ms);
foreach ($infos as $key => $value) {
$output->writeln(" <comment>>></comment> $key: " . str_repeat(' ', 50 - strlen($key)) . $value);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uh, what's this weird string <comment>>></comment> ? Purpose ? Explain in a PHP comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bildschirmfoto von 2017-01-31 17-19-58

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhhhhh got it

}
}

public function getMigrationsInfos(MigrationService $ms) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PHPDoc: @return array associative array of human readable info name as key and the actual information as value


public function changeSchema(Schema $schema, array $options) {
$prefix = $options['tablePrefix'];
if (!$schema->hasTable("${prefix}external_mounts")) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need the prefix ? I thought it was set on the connection already ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not possible at the moment because the schema class is disconnected to the connection.
The schema as generated from the database holds the prefix already - so when comparing we need to add it.

I'm not yet that happy about this - we might need to subclass Schema or introduce ISchema.
I will do this in a follow up PR - this PR is at it's limits

/**
* @param Schema $schema
*/
public function down(Schema $schema) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove ?

@@ -42,14 +42,10 @@

class Migrator {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deprecated ?

@PVince81

Copy link
Copy Markdown
Contributor

Please check my comments then 👍

@DeepDiver1975

Copy link
Copy Markdown
Member Author

Shall we kill ITransactionalStep for now? Just to keep it simpler? @PVince81

@PVince81

Copy link
Copy Markdown
Contributor

Shall we kill ITransactionalStep for now? Just to keep it simpler?

I'd say yes, let's remove it.

In general my intuitive feeling when writing migrations was that the migration itself is always within a transaction. So every migration run would have its own transaction. And maybe the top level that runs all migrations also has a parent transaction.

@DeepDiver1975 DeepDiver1975 merged commit 97e8f39 into master Feb 1, 2017
@DeepDiver1975 DeepDiver1975 deleted the owncloud-migrations branch February 1, 2017 14:12
@PVince81

PVince81 commented Feb 1, 2017

Copy link
Copy Markdown
Contributor

🎉

@lock

lock Bot commented Aug 4, 2019

Copy link
Copy Markdown

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock Bot locked as resolved and limited conversation to collaborators Aug 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants