Problem/Motivation

Was trying to use highwater fields, and notices a number of problems.

  1. The highwater support is spread among the source plugin, migration plugin, and MigrateExecutable classes, yet really is purely a source-specific feature and should be contained to the source plugin.
  2. The configuration property highWaterProperty violated Drupal naming standards.
  3. The config schema is missing, so it's actually not possible to define a migration with that in the first place :) No longer applicable since migrations are now plugins, not configuration entities.
  4. SqlBase, when building the query, uses $high_water for *both* the name of the field and the value, so the field name overwrites the value, and it builds a query like this: condition('changed', 'changed', '>')
  5. Also, in there, I *think* we should additionally add a orderBy($high_water_field), otherwise it could happen that we set the value to a random higher value and still have records with lower values that are not migrated, or the other way round, that we send the high water value lower again and have to re-import stuff

    Example:
    You have 3 records. changed 1, 3, 2. you import the first two, 1, 3. highwater is set to the last one you imported, 3, and 2 is never imported. or the other way round, they are in this order: 3, 2, 1. 1 is the last one to be imported, so the highwater field at the end is 1 and 2 and 3 will be imported again.

    (assuming a partial import for some scenarios above)

  6. Again assuming that you're doing a partial import, if you have a lot of records with the same value there and don't import them all, it could happen then you skip some. let's say you have 100 records with a value of 1. then you import 50 of them and set highwater value to 1. the next time the query runs, it will do changed > 1 and the other 50 records will be skipped

    => So the query condition should be =>. Values with identical records will have to be loaded again, and possibly require additional special casing somewhere. If they are in the map and have the same value, then it's probably OK. If they are not in the map at all yet, we need to import them.

Proposed resolution

  1. Fix the SqlBase optimization to properly incorporate the highwater value test.
  2. Rename highWaterProperty to high_water_property.
  3. Move all highwater support within the source plugin.

Remaining tasks

None.

User interface changes

N/A

API changes

  1. highWaterProperty renamed to high_water_property, and moved from the top-level migration plugin configuration into the source plugin configuration.
  2. high_water_property subfield 'field' renamed to 'name'.
  3. Public methods getHighWater(), getHighWaterProperty(), and saveHighWater() removed from MigrationInterface.
CommentFileSizeAuthor
#183 interdiff.txt936 bytesmikeryan
#183 move_highwater_field-2485385-183.patch41.51 KBmikeryan
#180 move_highwater_field-2485385-180.patch40.46 KBmikeryan
#176 move_highwater_field-2485385-176-do-not-commit.patch76.53 KBmikeryan
#174 2485385-174-8.2.x.patch41.22 KBphenaproxima
#165 interdiff.txt786 bytescatch
#165 2485385-165.patch41.24 KBcatch
#162 155-161-interdiff.txt3.41 KBalexpott
#161 2485385-2-161.patch43.12 KBalexpott
#161 155-161-interdiff.txt782 bytesalexpott
#159 2485385-159.patch42.01 KBalexpott
#159 155-159-interdiff.txt2.31 KBalexpott
#155 move_highwater_field-2485385-155.patch41.24 KBheddn
#151 2485385-151.patch45.11 KBalexpott
#151 144-151-interdiff.txt782 bytesalexpott
#144 interdiff-null.txt990 bytesxjm
#144 2485385-144.patch40.47 KBxjm
#128 interdiff-2485385-121-128.txt407 bytesphenaproxima
#128 2485385-128.patch40.47 KBphenaproxima
#121 interdiff-2485385-116-121.txt5.44 KBphenaproxima
#121 2485385-121.patch40.54 KBphenaproxima
#116 interdiff-2485385-115-116.txt792 bytesphenaproxima
#116 2485385-116.patch37.69 KBphenaproxima
#115 interdiff-2485385-112-115.txt982 bytesphenaproxima
#115 2485385-115.patch38.15 KBphenaproxima
#112 interdiff-2485385-105-112.txt6.7 KBphenaproxima
#112 2485385-112.patch38.44 KBphenaproxima
#105 interdiff-2485385-104-105.txt621 bytesphenaproxima
#105 2485385-105.patch37.1 KBphenaproxima
#104 interdiff-2485385-102-104.txt2.6 KBphenaproxima
#104 2485385-104.patch37.36 KBphenaproxima
#102 interdiff-2485385-100-102.txt2.65 KBphenaproxima
#102 2485385-102.patch36.86 KBphenaproxima
#100 interdiff-2485385-98-100.txt7.03 KBphenaproxima
#100 2485385-100.patch34.07 KBphenaproxima
#98 interdiff-2485385-97-98.txt4 KBphenaproxima
#98 2485385-98.patch31.15 KBphenaproxima
#97 interdiff-2485385-82-97.txt7.95 KBphenaproxima
#97 2485385-97.patch31.38 KBphenaproxima
#95 interdiff-2485385-93-95.txt9.25 KBphenaproxima
#95 2485385-95.patch48.83 KBphenaproxima
#93 interdiff-2485385-91-93.txt2.45 KBphenaproxima
#93 2485385-93.patch41.17 KBphenaproxima
#91 interdiff-2485385-89-91.txt5.04 KBphenaproxima
#91 2485385-91.patch39.67 KBphenaproxima
#89 interdiff-2485385-87-89.txt1.26 KBphenaproxima
#89 2485385-89.patch34.83 KBphenaproxima
#87 interdiff-2485385-82-87.txt10.74 KBphenaproxima
#87 2485385-87.patch34.54 KBphenaproxima
#82 interdiff.txt17.09 KBquietone
#82 migrate_highwater-2485385-82.patch25.45 KBquietone
#80 interdiff.txt747 bytesquietone
#80 migrate_highwater-2485385-80.patch19.52 KBquietone
#76 interdiff.txt7.43 KBquietone
#76 migrate_highwater-2485385-76.patch19.58 KBquietone
#67 interdiff.txt559 bytesquietone
#67 migrate_highwater-2485385-67.patch17.69 KBquietone
#65 interdiff.txt4.16 KBquietone
#65 migrate_highwater-2485385-65.patch17.69 KBquietone
#56 migrate_highwater-2485385-56.patch17.81 KBhussainweb
#56 interdiff-52-56.txt3.26 KBhussainweb
#52 migrate_highwater-2485385-52-test-only.patch17.25 KBquietone
#50 migrate_highwater-2485385-50-test-only.patch17.24 KBquietone
#40 migrate_highwater-2485385-40.patch18.2 KBquietone
#29 migrate_highwater-2485385-29.patch20.31 KBblazey
#28 migrate_sqlbase_highwater_test-2690757-2.patch9.8 KBblazey
#22 migrate-highwater-test-2485385-21-test-only-do-not-test.patch2.38 KBberdir
#21 interdiff-2485385-18-21.txt3.94 KBphenaproxima
#22 migrate-highwater-test-2485385-21-test-only-do-not-test.patch2.38 KBberdir
#18 interdiff-2485385-14-18.txt420 bytesphenaproxima
#18 2485385-18.patch7.61 KBphenaproxima
#16 2485385-16-test-only.patch777 bytesphenaproxima
#14 interdiff-2485385-10-14.txt4.72 KBphenaproxima
#14 2485385-14.patch7.1 KBphenaproxima
#10 interdiff-2485385-9-10.txt1.58 KBphenaproxima
#10 2485385-10.patch6.27 KBphenaproxima
#9 interdiff-2485385-1-9.txt3.97 KBphenaproxima
#9 2485385-9.patch4.22 KBphenaproxima
#1 migrate-highwater-2485385-1.patch1.65 KBberdir

Comments

berdir’s picture

Status: Active » Needs review
StatusFileSize
new1.65 KB

patch with some fixes, does not yet address 4.

Status: Needs review » Needs work

The last submitted patch, 1: migrate-highwater-2485385-1.patch, failed testing.

mikeryan’s picture

  1. +++ b/core/modules/migrate/config/schema/migrate.schema.yml
    @@ -19,6 +19,8 @@ migrate.migration.*:
    +    highWaterProperty:
    

    Coding standard is underscore-separated. Also, I think "field" is better than "property" here.

  2. +++ b/core/modules/migrate/config/schema/migrate.schema.yml
    @@ -19,6 +19,8 @@ migrate.migration.*:
    +      type: mapping
    

    Needs to be fleshed out farther, defining 'name' as required and 'alias' as optional.

  3. +++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
    @@ -175,12 +175,13 @@ protected function initializeIterator() {
    +        $this->query->orderBy($high_water_field);
    

    In Migrate Classic™, properly ordering the query has been the responsibility of whoever defined the query. I'm a little concerned automatically forcing the order here might not work for all queries. Also, in some cases the query definer might want to use a second (or beyond) field for ordering when there are dupes in the highwater field.

berdir’s picture

1. I'm just adding the schema based on how the code is already using it. Changing it here would result in a much bigger patch.. Could be argued that's ok since it's broken right now anyway.

2. Yes ;) That was the minimium to get it imported ;)

3. You don't write source queries yourself anymore for many cases. But yes, I was wondering about this too. But if we can automatically add a condition, then it should be fine to add an order by as well? It's the source base class, if you have a different query, you can always change it...

berdir’s picture

One more problem.

if (isset($high_water_property['name']) && ($high_water = $this->migration->getHighWater()) !== '') {

I know that the migrate people like type safe checks, but type safe checks when there actually is no type safety guaranteed is bad.

getHighWater() on the first run returns NULL, not a string.

benjy’s picture

getHighWater() on the first run returns NULL, not a string.

o, that never used to be the case in D7, from memory it was an empty string.

berdir’s picture

That's possible, but it's based on the key value store in 8.x, and the default value is NULL there. You could pass in '' as a default value, but IMHO, NULL makes a lot more sense than an empty string for that...

benjy’s picture

IMHO, NULL makes a lot more sense than an empty string for that...

Yes I agree, I was just pointing out before that it was likely un-changed code (or logic) from D7.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new4.22 KB
new3.97 KB

Made a few changes here.

First, I think that the high-water property should be defined as part of the source plugin's configuration, not as a top-level property of the migration. High-water properties don't apply to all migrations; and for migrations that do use them, they only have any meaning to the source plugin anyway. And on top of that, they really (so far, anyway) only have meaning for SQL-based sources. So this patch alters the config schema so that high_water_property is a property of the migrate_source_sql data type.

Secondly, there were a couple of PHPUnit tests which ostensibly use high-water properties, but they were not setting values which would actually be used by the SqlBase plugin (it was looking for $high_water_property['name'], and the tests were setting $high_water_property['field']). That's fixed now.

phenaproxima’s picture

StatusFileSize
new6.27 KB
new1.58 KB

Whoops, forgot to adjust a few tests.

berdir’s picture

Status: Needs review » Needs work
+++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
@@ -173,15 +172,19 @@ protected function initializeIterator() {
+        if (isset($high_water_property['name']) && ($high_water = $this->migration->getHighWater()) !== '') {

See #5, a type safe check here doesn't make sense, since this will return NULL if there's nothing. Or getHighWater() needs to cast to a string().

Other than that nice. I don't think this addresses all my concerns, but let's get something in and then we improve it further later.

Probably also needs some actual tests with an actual config entity or at least failing due to the wrong code?

phenaproxima’s picture

Looking at the Migration class, we might have to restore highWaterProperty to the config schema, because $highWaterProperty is a property of the Migration entity type, so methods probably depend on it. What do you think?

I totally agree this should have some real tests.

benjy’s picture

And on top of that, they really (so far, anyway) only have meaning for SQL-based sources.

Why? If you handle it in your custom source it should work just fine?

phenaproxima’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new7.1 KB
new4.72 KB

Re-added the high water property to config schema and fixed broken tests (which were using a nonsensical high-water property in their $migrationConfiguration, thus causing SQL errors -- another example of something that had never worked, but been covered up by age and bugs).

There already is at least one passing test which uses the high-water property (CommentSourceWithHighWaterTest), so I'm removing the "needs tests" tag.

Status: Needs review » Needs work

The last submitted patch, 14: 2485385-14.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new777 bytes

This fixes the only real test of high-water property support (CommentSourceWithHighWaterTest) against HEAD, to prove the problem actually exists and is rectified by the patch in #18.

phenaproxima’s picture

Derp, duplicate comment.

phenaproxima’s picture

StatusFileSize
new7.61 KB
new420 bytes

Fixing them thar test failures in #14.

The last submitted patch, 16: 2485385-16-test-only.patch, failed testing.

berdir’s picture

  1. +++ b/core/modules/migrate/config/schema/migrate.data_types.schema.yml
    @@ -27,6 +27,16 @@ migrate_source_sql:
           label: 'The migration database target'
    +    high_water_property:
    +      type: mapping
    +      label: 'High-water property'
    +      mapping:
    +        name:
    +          type: string
    

    This should be removed now?

  2. +++ b/core/modules/migrate/config/schema/migrate.schema.yml
    @@ -16,6 +16,16 @@ migrate.migration.*:
    +    highWaterProperty:
    +      type: mapping
    +      label: 'High-water property'
    +      mapping:
    +        name:
    

    So, camel case or not? :)

  3. +++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
    @@ -173,15 +172,18 @@ protected function initializeIterator() {
    +      if ($high_water_property = $this->migration->get('highWaterProperty')) {
    +        if (isset($high_water_property['name']) && ($high_water = $this->migration->getHighWater()) !== NULL) {
    

    So this is now a type save check against NULL.

    We should update the documentation of that method to say that it can return NULL if there is no value yet, and enforce that this is the case ?: NULL or so, and not FALSE or '' or 0.

    Also, the testcase base class still defaults to an empty ''. We should also make sure that ensures that the method is called if we define it (atleastOnce()).

phenaproxima’s picture

StatusFileSize
new8.94 KB
new3.94 KB

All fixed.

berdir’s picture

Status: Needs review » Postponed
StatusFileSize
new2.38 KB
new2.38 KB

Played a bit with the test.

This is kind of how I'd expect a highwater test to look like. Making sure that there actually are more rows in the database than we'd expect (the test passes on HEAD but that's completely bogus since there is nothing else that it could return) + some asserts on the actual query object.

Also removed an order by from the comment source. I think that's not needed now that sql base is adding that automatically.. not sure if it was an attempt to make high water work in the past. I don't think we should rely on the source to add the correct order.

This will fail right now because the tests hardcode the assumption that count($source) needs to return the same count as results.. but that is not the case if you are using highwater and according to @mikeryan that is by design (although it is not quite clear to me how you'd then display a useful count of how much still needs to be imported?). The good thing is that #2499793: Several migrate_drupal migrations fatal error on count() is going to fix that behavior for us and then we can define the test so that it expects a different count for that query. So we'll wait on that...

There is one other scenario that we should be testing to test the NULL/'' behavior. And that would be yet another test that defines a highwater property but no original highwater value. Maybe the property should just be set in CommentTestBase. The result is that it must not add the condition then. Thinking about it, we might have another hidden bug there.. because the order by *has* to be there even if there is no current value.. so that we process them in the right order.

phenaproxima’s picture

Status: Postponed » Needs review

Unblocked.

berdir’s picture

Status: Needs review » Needs work

Yes. pretty sure this needs work, though :)

berdir’s picture

+++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
@@ -114,7 +114,6 @@ protected function prepareQuery() {
   protected function initializeIterator() {
     $this->prepareQuery();
-    $high_water_property = $this->migration->get('highWaterProperty');
 

high_water_property vs highWaterProperty is still inconsistent. See for example SourcePluginBase::__construct() and MigrateExecutable::import().

So we are definitely still missing test coverage..

We are testing the sql source that automatically filters, but we are not checking that the saved value is updated and a second run will then use an updated value.

I've been testing this with a custom source and one additional problem that I kind of mentioned before is order. We either need to document that source plugins *must* return the records sorted by the highwater field if supporter or somehow be able to deal with them not being ordered. For example, not assume that the last row has the highest highwater value, which is what MigrateExecutable::import() currently does, but keep the highest value of all rows.

blazey’s picture

Hi, I've also been trying to fix high water property. My solution is very similar so I won't post it here. The Kernel test, however, could be useful (https://www.drupal.org/node/2690757#comment-10988135). Shall I create a separate issue containing just the test?

berdir’s picture

Please add the test here. Missing tests is the main reason this isn't moving forward.

blazey’s picture

Attaching Kernel test.

blazey’s picture

Status: Needs work » Needs review
StatusFileSize
new20.31 KB

Attached patch is an attempt to combine migrate_sqlbase_highwater_fix-2690757-7.patch and 2485385-21.patch (re-rolled).

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

heddn’s picture

Version: 8.1.x-dev » 8.2.x-dev
Status: Needs review » Needs work

This needs a re-roll after #2694009: MigrationInterface doesn't include get() was committed.

heddn’s picture

Also, if we rename the high water property, we might consider changing the name of the associated getter too.

mikeryan’s picture

rakesh.gectcr’s picture

Assigned: Unassigned » rakesh.gectcr
rakesh.gectcr’s picture

Assigned: rakesh.gectcr » Unassigned
heddn’s picture

Issue tags: +Novice

The next step here is to replace all the

->get('foo')

calls to ->getFoo() calls.

The last submitted patch, 29: migrate_highwater-2485385-29.patch, failed testing.

mikeryan’s picture

Issue tags: +Migrate critical

We have a Major issue for documented functionality that is badly broken - how did we never set it to migrate-critical?

mikeryan’s picture

Issue tags: -Novice +Needs reroll

Looked at the last patch, it needs more than the get() calls changed (still based on migrations as configuration entities).

quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new18.2 KB

I'm working on rerolling the patch from #29 and stuck on errors from this test, core/modules/migrate/tests/src/Kernel/SQLBaseTest.php. The error is:

    Drupal\Tests\migrate\Kernel\SQLBaseTest::testSQLMigration
    Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException:
    You have requested a non-existent service
    "plugin.manager.migrate.cckfield".

Testing the patch as is to see what else is broken.

Status: Needs review » Needs work

The last submitted patch, 40: migrate_highwater-2485385-40.patch, failed testing.

mikeryan’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll

Requeued the test, I don't see why it would trigger that error.

Status: Needs review » Needs work

The last submitted patch, 40: migrate_highwater-2485385-40.patch, failed testing.

mikeryan’s picture

Not a complete review, just trying to guess at what might be triggering the test failure...

+++ b/core/modules/migrate/tests/modules/migrate_sql_source_test/migrate_sql_test.module
--- /dev/null
+++ b/core/modules/migrate/tests/modules/migrate_sql_source_test/migration_templates/migrate.migration.sql_test.yml

Now that migrations are plugins rather than config entities, 'migrate.migration.' should not be part of the .yml filename.

phenaproxima’s picture

Status: Needs work » Postponed

Postponing on #2560795: Source plugins have a hidden dependency on migrate_drupal. @mikeryan and I think that it's the reason for the mysterious test failure in #40.

mikeryan’s picture

Status: Postponed » Needs review

The blocker is committed, let's retest.

Status: Needs review » Needs work

The last submitted patch, 40: migrate_highwater-2485385-40.patch, failed testing.

quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new17.24 KB

Even though this is still blocked I want to address the failures and be ready for when it is unblocked.

The error was a result of the source test table being created in the destination database. The table was being created by the test module and that is now being done in the test, HighWaterTest.php.

And there is a lot of renaming in this patch as well. The high water test has been renamed from SQLBaseTest to HighWaterTest since it is testing the high water functionality and it follows the naming convention. The test module has been renamed to migrate_high_water_test In a similar fashion the test source plugin, the test table and the migration have all had a name change. I think it is much clearer that these are for high water tests and nothing else.

In order to run these tests without the blocker patch, the modules 'migrate_drupal' and 'fields' are installed in HighWaterTest.php. It is marked with an @todo, that seemed the best way to mark it.

Now let's see if there are any other errors.

Status: Needs review » Needs work

The last submitted patch, 50: migrate_highwater-2485385-50-test-only.patch, failed testing.

quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new17.25 KB

Not sure how that error slipped in.

Status: Needs review » Needs work

The last submitted patch, 52: migrate_highwater-2485385-52-test-only.patch, failed testing.

quietone’s picture

Retesting. Failure in OptionsFieldUITest.php appears to be unrelated, and that test passes locally .

The last submitted patch, 52: migrate_highwater-2485385-52-test-only.patch, failed testing.

hussainweb’s picture

Status: Needs work » Needs review
StatusFileSize
new3.26 KB
new17.81 KB

I tried to make the high water mark logic a bit simpler with a new method. Also, I am not sure why the patch was named as 'test-only'. I checked the patches before and it seemed to be the whole patch file.

Status: Needs review » Needs work

The last submitted patch, 56: migrate_highwater-2485385-56.patch, failed testing.

hussainweb’s picture

hussainweb’s picture

Status: Needs work » Needs review

The failure is resolved.

chx’s picture

Thanks for writing this. This is a very nice patch. But if you are breaking BC anyways, then please understand the sorry state for highwater and everything else baked into SourcePluginBase::next() is the very reason I am advocating for breaking up source into an iterator, into row additions and filters in #2543552: Modernize migration source plugins. If people would have the time and the willingness to work on it, would be great. It is extremely hard for me to just go and code some core because it would be nicer. I don't have such willingness for that after all that transpired. I just don't. I know what needs to be done but I can't.

The test from this patch could mostly be reused, most of the highwater functionality could be reused as well.

hussainweb’s picture

@chx, thank you for pointing me to that issue. I will try to catch up on the discussion in the coming week.

I was also not very concerned about breaking BC because migrate is experimental and we have done things like this in the past.

chx’s picture

> I was also not very concerned about breaking BC because migrate is experimental

Wish certain elements of the community agreed with you.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

phenaproxima’s picture

I think this looks great. My only complaints are nitpicks.

  1. +++ b/core/modules/migrate/tests/src/Kernel/HighWaterTest.php
    @@ -0,0 +1,189 @@
    +      ->values(
    +        [
    +          'title' => 'Item 1',
    +          'changed' => 1,
    +        ])
    +      ->values(
    +        [
    +          'title' => 'Item 2',
    +          'changed' => 2,
    +        ])
    +      ->values(
    +        [
    +          'title' => 'Item 3',
    +          'changed' => 3,
    +        ]
    +      )
    

    Bit of a nitpick, but can we follow the formatting used in ->fields()? (i.e., the opening bracket of each array on the same line as the opening paren)

  2. +++ b/core/modules/migrate/tests/src/Kernel/HighWaterTest.php
    @@ -0,0 +1,189 @@
    +  public function testHighWater() {
    +
    +    // Assert all of the nodes have been imported.
    

    Extra empty line.

  3. +++ b/core/modules/migrate/tests/src/Kernel/HighWaterTest.php
    @@ -0,0 +1,189 @@
    +    // Update Item 1 setting it's high_water_property to value that is below
    

    Nit: it's should be its.

  4. +++ b/core/modules/migrate/tests/src/Kernel/HighWaterTest.php
    @@ -0,0 +1,189 @@
    +      ->fields(
    +        [
    +          'title' => 'Item 3 updated',
    +          'changed' => 4,
    +        ])
    

    Should be ->fields([...

  5. +++ b/core/modules/migrate/tests/src/Unit/MigrateSqlSourceTestCase.php
    @@ -82,6 +82,14 @@ protected function setUp() {
    +        ->will($this->returnValue(static::ORIGINAL_HIGH_WATER));
    

    Let's use willReturnValue() for readability.

quietone’s picture

StatusFileSize
new17.69 KB
new4.16 KB

All nitpicks fixed.

Status: Needs review » Needs work

The last submitted patch, 65: migrate_highwater-2485385-65.patch, failed testing.

quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new17.69 KB
new559 bytes

Fixed typo.

phenaproxima’s picture

Thanks, @quiteone. This looks pretty righteous to me, but I'd like to the RTBC to come from one of Migrate's expert plumbers (@benjy, @chx, or @mikeryan)...

benjy’s picture

Patch looks good to me.

One confusing aspect is we now have getHighWaterProperty(), getHighWater() and getHighWaterField() all on the migration. Probably out of scope here but it would have been nice to have a HighWater value object that encapsulated those methods, and just have the one getHighWater() method on the migration. Alternatively, MigrateExecutable is now the only thing calling getHighWaterProperty()like so:

      if ($high_water_property = $this->migration->getHighWaterProperty()) {
        $this->migration->saveHighWater($row->getSourceProperty($high_water_property['name']));
      }

We could easily change that so that the executable didn't need any knowledge of the high water property at all?

      if ($high_water_property = $this->migration->supportsHighWater()) {
        $this->migration->saveHighWater($row);
      }

Maybe a follow-up?

ayalon’s picture

I tested the patch but in my humble opinion, only the test works but beside that patch is not working.

The problem is, that in the test the configuration for the property is set up:

  protected function setUp() {
    $this->migrationConfiguration['high_water_property']['name'] = 'timestamp';
    array_shift($this->expectedResults);
    parent::setUp();
  }

But outside of the test, the yml configuration never gets picked up and therefore the whole highwater stuff is not working. Any suggestions?

ayalon’s picture

*edited* seems not to be a solution.

ayalon’s picture

I try to debug the highwater functionality and while debugging, I found out, that the highwater value is saved for every row:

web/core/modules/migrate/src/MigrateExecutable.php

      if ($high_water_property = $this->migration->getHighWaterProperty()) {
        $this->migration->saveHighWater($row->getSourceProperty($high_water_property['name']));
      }

As there is only one field in the KeyValueStore, does it really make sense to save the date for every row?

berdir’s picture

That is unrelated to this ticket and on purpose. The migration could die with a fatal error any time and it does this to make sure that the highwater value is accurate.

quietone’s picture

Created a follow up issue as suggested in #69, #2785233: Encapsulate HighWater methods

mikeryan’s picture

Status: Needs review » Needs work

Sorry I haven't looked closely at this for a while - the implementation looks good, but I agree with phenaproxima's comment back in #9 - this configuration belongs on the source plugin, not on the migration.

quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new19.58 KB
new7.43 KB

OK. Patch reworked to put the high water on the source plugin. Also, had to modify MigrateSqlSourceTestCase so that the expectations (is the right way to say that) are set only on testRetrieval. That is the only method that initializes the iterator which is where the high water checks are.

Status: Needs review » Needs work

The last submitted patch, 76: migrate_highwater-2485385-76.patch, failed testing.

quietone’s picture

Status: Needs work » Needs review

Hmm, the status changed to Needs work while the test in #76 was still running. It did in fact pass, so changing to Needs review.

phenaproxima’s picture

  1. +++ b/core/modules/migrate/src/Plugin/Migration.php
    @@ -703,17 +703,20 @@
    +    if (isset ($this->getSourceConfiguration()['high_water_property'])) {
    +      $high_water_property = $this->getSourceConfiguration()['high_water_property'];
    

    Why not simply call $this->getHighWaterProperty()?

  2. +++ b/core/modules/migrate/src/Plugin/migrate/source/SqlBase.php
    @@ -210,20 +210,19 @@
    +    if (isset($this->configuration['high_water_property'])) {
    +      $high_water_property = $this->configuration['high_water_property'];
    

    Ditto here.

quietone’s picture

StatusFileSize
new19.52 KB
new747 bytes

Darn. Meant to fix that.

mikeryan’s picture

Version: 8.3.x-dev » 8.2.x-dev
Status: Needs review » Needs work

Looks good - and tested in the (semi-)real world, at #2609310: Add highwater/track_changes examples to beer migrations. However, one more thing - there's really no logical reason for the Migration plugin to know anything about highwater marks, it should all be entirely contained within the source plugin. Now, while we're already breaking BC by changing the highwater property name, that's not a big deal (especially since it didn't really work) - but changing MigrationInterface would be. So, my suggestion is:

  1. Copy all the highwater stuff currently in Migration into SourcePluginBase, and interfaces from MigrationInterface to MigrateSourceInterface.
  2. Deprecate the public highwater methods on MigrationInterface, to be removed in 8.3.x.
  3. Make the Migration implementations of those public methods wrappers around the SourcePluginBase methods.
  4. Remove the saveHighwater() call from MigrateExecutable - do it in SourcePluginBase::next() instead, at the end of the loop (after aboveHighwater() is used).
quietone’s picture

Status: Needs work » Needs review
StatusFileSize
new25.45 KB
new17.09 KB

@mikeryan, thanks for breakdown of the tasks. I usually think in lists, so that was helpful, and clear. Everything has been addressed but these are my first deprecations and wrappers. And there are still failing tests. Hopefully, only MigrateSourceTest.php and CommentSourceWithHighWaterTest.php.

  1. For item #4, there were two uses of saveHIghWater in MigrateExecutable, the one at the end of the import loop has been removed but the one in the rollback remains.
  2. The spelling is HighWater in the methods and properties, except for aboveHighwater. Should we change that to aboveHighWater?
  3. I think the unit tests fail becuase getHighWater always returns NULL. Whatever I tried was wrong so the original, now incorrect, setup of getHighWater is unchanged.

Status: Needs review » Needs work

The last submitted patch, 82: migrate_highwater-2485385-82.patch, failed testing.

The last submitted patch, 82: migrate_highwater-2485385-82.patch, failed testing.

The last submitted patch, 82: migrate_highwater-2485385-82.patch, failed testing.

phenaproxima’s picture

Assigned: Unassigned » phenaproxima
phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new34.54 KB
new10.74 KB

I am praying to Cthulhu that this passes the tests. It turns out we ran smack-dab into dependency injection hell with this one -- MigrateSqlSourceTestCase (upon which many if not all source plugin tests are based) is a unit test, and the patch in #82 was trying to pull the high water value directly out of \Drupal -- and understandably so, because adjusting the dependencies is quite tricky. This patch removes getHighWaterStorage() in favor of actual dependency injection, which involves changing base class constructors. That constitutes a BC break, but that's OK because this issue was already tagged as such.

MigrateSqlSourceTestCase is, in my opinion, a mess. It's doing a lot of mocking and set-up that would be totally unnecessary if it were a kernel test, and this patch does nothing to fix that -- in fact, by introducing a new mockContainer() method, it might even be exacerbating the problem. But rewriting MigrateSqlSourceTestCase as a kernel test is very far out of the scope of this patch, so we'll have to get to it later.

Status: Needs review » Needs work

The last submitted patch, 87: 2485385-87.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new34.83 KB
new1.26 KB

Screwed up the mocked keyvalue service. Derp.

Status: Needs review » Needs work

The last submitted patch, 89: 2485385-89.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new39.67 KB
new5.04 KB

Missed a spot or two. If nothing else, this should greatly reduce the number of failures.

Status: Needs review » Needs work

The last submitted patch, 91: 2485385-91.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new41.17 KB
new2.45 KB

Okay...as of this patch, SourcePluginBase itself now implements ContainerFactoryPluginInterface. Kind of a sweeping change, but this does open the door to proper dependency injection for all source plugins. So it's a win for best practices, but hopefully not so far out of scope that we can no longer commit it. (If it is, I have yet another trick up my sleeve.)

Status: Needs review » Needs work

The last submitted patch, 93: 2485385-93.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new48.83 KB
new9.25 KB

At long last, a shattered and shell-shocked phenaproxima (hopefully) crosses the finish line. Working on our source plugin tests is like stumbling blind through a thorny jungle in hell.

mikeryan’s picture

Status: Needs review » Needs work

I'm not sure how I feel about about changing SourcePluginBase - that's a more far-reaching change than I had hoped. But, it may be necessary, I see...

Why are public functions added to MigrateSourceInterface? Highwater support should be entirely encapsulated within the source plugin, the internals shouldn't be exposed.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new31.38 KB
new7.95 KB

Okay. This patch fixes the tests without imposing DI on everything. It's messy as all hell, but that is because the source plugin tests are so awful -- they mock the universe, and they have to be incredibly careful about when they do things, or the whole house of cards implodes. It's a nightmare. Let's get #2791119: Write meaningful Migrate source tests in ASAP and we can start to undo the damage.

I still need to hide all the high-water stuff from outside code, but that should be relatively easy now that the tests are passing. On my local machine, anyway.

phenaproxima’s picture

StatusFileSize
new31.15 KB
new4 KB

OK, this removes the changes to MigrateSourceInterface and makes the high-water methods of SourcePluginBase protected.

Status: Needs review » Needs work

The last submitted patch, 98: 2485385-98.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new34.07 KB
new7.03 KB

OK, so...the source plugin needs to be able to reset the high-water mark once rollback is complete. After discussion with @mikeryan on IRC, we agreed that the best way to do that was to allow source and destination plugins to be event subscribers and react to various events dispatched by MigrateExecutable. That's what I've done here. Dear lordy, let it pass the tests.

Status: Needs review » Needs work

The last submitted patch, 100: 2485385-100.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new36.86 KB
new2.65 KB

And that, kids, is why I don't like using invocation assertions in unit tests.

mikeryan’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/migrate/src/Plugin/Migration.php
    @@ -703,7 +662,7 @@ public function getSourceConfiguration() {
       public function getHighWaterProperty() {
    -    return $this->highWaterProperty;
    +    return $this->getSourcePlugin()->getHighWaterProperty();
       }
    

    Why weren't we able to remove this from the Migration plugin along with the rest of the highwater methods?

  2. +++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
    @@ -60,6 +53,20 @@
    +  /**
    +   * @var \Drupal\Core\KeyValueStore\KeyValueStoreInterface
    +   */
    

    Description needed.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new37.36 KB
new2.6 KB

Both fixed. I ran the migrate and migrate_drupal test suites before posting this patch, so I have high hopes that it will pass Drupal CI.

phenaproxima’s picture

StatusFileSize
new37.1 KB
new621 bytes

Removed a couple of dead use statements.

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

okie dokie!

xjm’s picture

Nice to see another Migrate critical RTBC!

This issue is technically rc eligible according to https://www.drupal.org/core/d8-allowed-changes#rc. However, given the importance of this issue, I'm actually going to tag it as an RC target so that it is a top priority to add during RC in case it is not committed before the commit freeze Tuesday morning.

The title and summary of this issue describe various problems but not the proposed resolution or the API changes. Can we get a CR for this issue and if possible retitle/re-summarize it to describe the fix? (The word "Various" in a title always makes me nervous.) :)

alexpott’s picture

+++ b/core/modules/migrate/src/MigrateExecutable.php
@@ -300,9 +300,28 @@ public function import() {
   /**
+   * Registers the source and destination plugins as event subscribers.
+   */
+  protected function registerEventSubscribers() {
+    $event_dispatcher = $this->getEventDispatcher();
+
+    $source = $this->migration->getSourcePlugin();
+    if ($source instanceof EventSubscriberInterface) {
+      $event_dispatcher->addSubscriber($source);
+    }
+
+    $destination = $this->migration->getDestinationPlugin();
+    if ($destination instanceof EventSubscriberInterface) {
+      $event_dispatcher->addSubscriber($destination);
+    }
+  }

+++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
@@ -417,4 +432,92 @@ protected function getCache() {
+    $events[MigrateEvents::POST_ROLLBACK][] = ['postRollback'];

Re-using the event system seems pretty clever but I wonder if it could get us into trouble. This could cause a double registration if the plugins were registered a services and tagged with 'event subscriber'. The double registration might occur if the an import and rollback occurred in the same process. Do we have other use-cases for this functionality other than listening to MigrateEvents::POST_ROLLBACK?

mikeryan’s picture

Title: Various problems with highwater field support » Cleanup of highwater field support
Issue summary: View changes
Issue tags: -Needs change record, -Needs issue summary update

Change record drafted and issue summary updated.

This could cause a double registration if the plugins were registered a services and tagged with 'event subscriber'.

Would a double registration cause the registered event handlers to be evoked multiple times, or is the dispatcher smart enough to dedupe them? I'll see if I can figure that out...

mikeryan’s picture

Status: Reviewed & tested by the community » Needs work

Yep, they get evoked multiple times.

@phenaproxima - what if we go back to calling $source->postRollback() directly, as was discussed in IRC along the way to this solution?

alexpott’s picture

We could have an interface on the plugin's to say that they have a postRollback method and call it if the plugins implement it.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new38.44 KB
new6.7 KB

Okay, I changed the approach. I think this way will please everybody.

I've created a new event subscriber that subscribes to the pre-import, post-import, pre-rollback, and post-rollback events. It handles the events by...calling the relevant methods on the source and destination plugins, if they implement them (which it verifies using method_exists()). I don't like the idea of having a new interface to define the event handling, because that's pretty much what EventSubscriberInterface is for.

phenaproxima’s picture

+++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
@@ -22,7 +21,7 @@
+abstract class SourcePluginBase extends PluginBase implements MigrateSourceInterface, RollbackAwareInterface {

RollbackAwareInterface is not a thing -- it's an artifact from another approach I tried. I could roll a new patch, but can it just be removed on commit?

Status: Needs review » Needs work

The last submitted patch, 112: 2485385-112.patch, failed testing.

phenaproxima’s picture

Status: Needs work » Needs review
StatusFileSize
new38.15 KB
new982 bytes
phenaproxima’s picture

StatusFileSize
new37.69 KB
new792 bytes

Iced unused implementation of getSubscribedEvents() in SourcePluginBase.

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

Let's do this thing!

xjm’s picture

Title: Cleanup of highwater field support » Move highwater field support to the source plugin, and do not expose its on MigrationInterface

Retitling based on the CR. Thanks @mikeryan!

xjm’s picture

Title: Move highwater field support to the source plugin, and do not expose its on MigrationInterface » Move highwater field support to the source plugin, and do not expose its internals on MigrationInterface
alexpott’s picture

Status: Reviewed & tested by the community » Needs review
  1. +++ b/core/modules/migrate/migrate.services.yml
    @@ -1,4 +1,8 @@
    +  migrate.plugin_event_subscriber:
    +    class: Drupal\migrate\Plugin\PluginEventSubscriber
    +    tags:
    +      - { name: event_subscriber }
    

    I really like the idea of a bridge service. Nice one.

  2. +++ b/core/modules/migrate/src/Plugin/PluginEventSubscriber.php
    @@ -0,0 +1,88 @@
    +    $source = $migration->getSourcePlugin();
    +    if (method_exists($source, $method)) {
    +      call_user_func([$source, $method]);
    +    }
    +
    +    $destination = $migration->getDestinationPlugin();
    +    if (method_exists($destination, $method)) {
    +      call_user_func([$destination, $method]);
    +    }
    

    Look like interfaces are appropriate here. That way we also get documentation (which this patch is lacking) for free. We need an interface per method (MigratePluginPreImportInterface etc...) Also I think we should pass the event to the method.

  3. +++ b/core/modules/migrate/src/Plugin/PluginEventSubscriber.php
    @@ -0,0 +1,88 @@
    +    $this->invoke('preImport', $event->getMigration());
    ...
    +    $this->invoke('postImport', $event->getMigration());
    ...
    +    $this->invoke('preRollback', $event->getMigration());
    ...
    +    $this->invoke('postRollback', $event->getMigration());
    

    here we could pass the invoke method the interface as well as the method to make checking it simple.

phenaproxima’s picture

StatusFileSize
new40.54 KB
new5.44 KB

Interfaces are appropriate, but I had decided to skip them for now in the name of getting this damn patch done, since it's one of the final blockers to Migrate API stability. I guess I don't mind putting interfaces on the plugins, but having an interface for each event seems clunky. I'd rather define two interfaces: ImportAwareInterface (defining preImport and postImport methods), and RollbackAwareInterface (preRollback and postRollback). So that's what I've done in this patch.

mikeryan’s picture

Looks good - just one more thing, can you update the change record to document the new interfaces?

phenaproxima’s picture

Since ImportAwareInterface and RollbackAwareInterface are not strictly related to the high-water fixes, I have opened a new change record.

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

Good call, thanks!

alexpott’s picture

+++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
@@ -324,6 +335,10 @@ public function next() {
+      if ($this->getHighWaterProperty()) {
+        $this->saveHighWater($row->getSourceProperty($this->highWaterProperty['name']));
+      }

So what's odd to me is that we save the highwater mark row by row on the way in but if we're rolling back we just null it at the end. Is there anyway we can make it right all the time? Ie... if a rollback breaks there is no guarantee that a user would reset the migrate status.

phenaproxima’s picture

Changing it would probably be a much bigger API break than this patch already constitutes. @mikeryan can confirm or deny that, but either way, it seems to me that changing migrations' highwater handling during rollback is well outside the scope of this issue. This patch is about getting highwater functionality to work the way it was always supposed to, but didn't due to a bug in SqlBase.

mikeryan’s picture

Is there anyway we can make it right all the time?

Consider if we rollback 10 items. To make the highwater "right" would require first that the 10 items rolled back would have been the last 10 imported. Actually, maybe the 10 with the highest source-side highwater field values would be strictly speaking the ideal. And then the highwater mark would need to be set to the source highwater field value of the 11th item - the next one to be rolled back. Keep in mind that the rollback process is an iterator (currently unsorted) over the map table, and does not use the source.

If someone wants to tackle this - good luck with that (in a followup - I think that's out of scope here). In the meantime, nulling the highwater mark is the safest recourse - the worst-case scenario if rollback is incomplete and for some reason the migrator decides to run an import rather than complete the rollback, the previously-imported items will be reimported. All that's lost is time, not data.

phenaproxima’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new40.47 KB
new407 bytes

Fixing a TODO pointed out by @alexpott. Seeing as how 128 is a holy computer number, it will be very satisfying if this is the one that gets committed. =P

phenaproxima’s picture

Status: Needs review » Reviewed & tested by the community

w00t! Back to RTBC.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 0308eb7 to 8.3.x and 7c8ebc3 to 8.2.x. Thanks!

Whilst reviewing this patch I pondered if we could set the highwater properly during rollback (see #125 and #127). After thinking about @mikeryan's response some more I think we should more the NULL setting from postRollback() to preRollback() this means that is the rollback fatals for any reason then the highwater is correctly indeterminate rather than wrong.

diff --git a/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
index 4b3da85..f393dc0 100644
--- a/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
+++ b/core/modules/migrate/src/Plugin/migrate/source/SourcePluginBase.php
@@ -452,7 +452,7 @@ protected function getHighWaterStorage() {
    * run. If the mark is set, only content with a higher timestamp will be
    * imported.
    *
-   * @return int|NULL
+   * @return int|null
    *   A Unix timestamp representing the high water mark, or NULL if no high
    *   water mark has been stored.
    */
@@ -491,7 +491,7 @@ protected function getHighWaterProperty() {
    *
    * @see \Drupal\migrate\Plugin\migrate\source\SqlBase::initializeIterator()
    *
-   * @return string|NULL
+   * @return string|null
    *   The name of the field for the high water mark, or NULL if not set.
    */
   protected function getHighWaterField() {

Fixed on commit. Yep we have automated coding standards for that :)

  • alexpott committed 0308eb7 on 8.3.x
    Issue #2485385 by phenaproxima, quietone, Berdir, blazey, hussainweb,...

  • alexpott committed 7c8ebc3 on 8.2.x
    Issue #2485385 by phenaproxima, quietone, Berdir, blazey, hussainweb,...
mikeryan’s picture

@alexpott: Good point, followup created: #2800715: Reset highwater mark *before* rolling back.

Thanks!

xjm’s picture

I'm pretty sure this just broke HEAD. Having trouble confirming locally because InstallUninstallTest is not exactly laptop-friendly.

chx’s picture

*knock, knock* is this on? Did anyone read #60? Why did this continue much less went in?

  • xjm committed b991ba9 on 8.3.x
    Revert "Issue #2485385 by phenaproxima, quietone, Berdir, blazey,...
xjm’s picture

Status: Fixed » Needs work

Confirmed. I had to roll this back. Here's the fail:
https://www.drupal.org/pift-ci-job/462223

Module.Drupal\system\Tests\Module\InstallUninstallTest
✓		- setUp
✗	
testInstallUninstall
fail: [Other] Line 210 of core/modules/system/src/Tests/Module/InstallUninstallTest.php:
Modules status has been updated.
✗	
rupal\migrate\Plugin\PluginEventSubscriber::getSubscribedEvents
exception: [Error] Line 86 of core/modules/migrate/src/Plugin/PluginEventSubscriber.php:
Class 'Drupal\migrate\Event\MigrateEvents' not found
✗	
nkno
fail: [Error] Line 86 of core/modules/migrate/src/Plugin/PluginEventSubscriber.php:
Class 'Drupal\migrate\Event\MigrateEvents' not found
xjm’s picture

@chx, #60 was answered. Migrate is in alpha. Until it is in beta, there is no BC promise. This issue is one of the last BC breaks listed as critical, so we are getting close to a beta that we all hope to have very soon.

Edit: Or if the question is "Why don't we break BC even more and block it on even better improvements," the answer is "because we want to get to a beta very soon".

mikeryan’s picture

So, MigrateEvents not found is something I've heard of before (without this patch) - people have reported it but I've never been able to reproduce it, nor figure out how that would happen - if migrate is enabled, the MigrateEvents class should be available. There's actually an open issue for this: #2776235: Cached autoloader misses cause failures when missed class becomes available

mikeryan’s picture

So, basically, there's nothing actually wrong with the highwater patch, it's that the event subscriber is triggering that existing autoloader issue. I'm curious, though, why it only surfaced after the commit?

xjm’s picture

@mikeryan, got me unfortunately. Usually I'd say something between the test run and commit but in this case that seems unlikely since the patch is right from this morning. It could be something @alexpott changed on commit causing a regression unexpectedly.

mikeryan’s picture

Retesting on 8.2.x and 8.3.x.

The last submitted patch, 128: 2485385-128.patch, failed testing.

xjm’s picture

StatusFileSize
new40.47 KB
new990 bytes

Here's the patch with @alexpott's coding standards fix; can't imagine this would have caused any difference. Maybe 8.2.x vs. 8.3.x.

xjm’s picture

Status: Needs work » Needs review

I queued both branches and all three PHP versions. The fail was across DBs in HEAD.

Status: Needs review » Needs work

The last submitted patch, 144: 2485385-144.patch, failed testing.

xjm’s picture

Ugh, sorry, I failed to push 8.2.x. Retesting those now that I did. And of course the 5.6 fail is irrelevant because of #2762549: Drupal\field\Tests\Update\FieldUpdateTest, Drupal\views\Tests\Update\EntityViewsDataUpdateTest and Drupal\comment\Tests\CommentFieldsTest fail on 8.1.x.

  • xjm committed 04953c5 on 8.2.x
    Revert "Issue #2485385 by phenaproxima, quietone, Berdir, blazey,...
phenaproxima’s picture

Ignoring the 5.6 failure (as per @xjm's comment in #147), I'm seeing two things:

1. The patch fails absolutely consistently on PHP 7.
2. We never tested the patch on PHP 7 (or, indeed, 5.6) before committing it.

I'm testing it locally on PHP 7 to see if that is the source of the problem.

chx’s picture

#138 let me clarify: I argued in #60 that this issue should be shuttered and the code reused in #2543552: Modernize migration source plugins which would break out highwater into its own plugin.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new782 bytes
new45.11 KB

So the problem is that on PHP7 content_translation is install before migrate and the autoloader caches the missing class in \Drupal\content_translation\ContentTranslationUpdatesManager::getSubscribedEvents(). The only way to fix it in this issue is to do a module exists check instead. Other possibilities are to change multiple module install to be batched and do one by one (slow) or the way would be to wrap the classloader in something that would make it possible to remove cached misses from the classmap.

Status: Needs review » Needs work

The last submitted patch, 151: 2485385-151.patch, failed testing.

phenaproxima’s picture

Issue tags: +Needs reroll
mikeryan’s picture

Interdiff looks good to me, pending reroll and test success - we can use #2776235: Cached autoloader misses cause failures when missed class becomes available for potentially following up with those other possibilities.

Thanks alexpott!

heddn’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new41.24 KB
heddn’s picture

Maybe @alexpott can comment on this, but the diff stats from #151 seem to also include some stuff for the outside_in module. I didn't include them in the re-roll. The diff stats make more sense when compared to #128.

alexpott’s picture

Version: 8.2.x-dev » 8.3.x-dev

Oopsie my diff included some stuff it should not... thanks @heddn

Status: Needs review » Needs work

The last submitted patch, 155: move_highwater_field-2485385-155.patch, failed testing.

alexpott’s picture

Version: 8.3.x-dev » 8.2.x-dev
Status: Needs work » Needs review
StatusFileSize
new2.31 KB
new42.01 KB

Okay so the module exists check is not going to work because we're inside a container rebuild and all bets are off :(

Therefore we need to replace the class loader when we update modules on the kernel.

I did not mean to change the version of this issue in #157 - sorry.

Status: Needs review » Needs work

The last submitted patch, 159: 2485385-159.patch, failed testing.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new782 bytes
new43.12 KB

New patch with the essential bits of #2776235: Cached autoloader misses cause failures when missed class becomes available just to see if it works...

alexpott’s picture

Title: Move highwater field support to the source plugin, and do not expose its internals on MigrationInterface » PrMove highwater field support to the source plugin, and do not expose its internals on MigrationInterface
StatusFileSize
new3.41 KB

Proper interdiff.

alexpott’s picture

Title: PrMove highwater field support to the source plugin, and do not expose its internals on MigrationInterface » Move highwater field support to the source plugin, and do not expose its internals on MigrationInterface
phenaproxima’s picture

Status: Needs review » Postponed

Heyo! Looks like @alexpott's fix corrects the problem. So it seems to me that we need to postpone this on #2776235: Cached autoloader misses cause failures when missed class becomes available which, I'm told, is going to be a critical.

Once this is unblocked, we'll need to re-roll this patch again, without the change to ContentTranslationUpdatesManager.

catch’s picture

Status: Postponed » Needs review
StatusFileSize
new41.24 KB
new786 bytes

Just want to see what happens with this. Event classes are one of my many complaints with the Symfony event system. interdiff is vs. #155

catch’s picture

So while the other bug is a real bug, we're also not doing ourselves any favours here either.

The hooks system allows modules to declare hook implementations regardless of whether another module is installed or not. The hook (like event listeners) only gets invoked when it's invoked anyway.

This works with event listeners, but the convention of putting the event name in an (arbitrary) constant on the event subclass discourages this, so we end up registering an event depending on whether the module that might invoke the event exists or not. What appears superficially to be more robust, turns out to be extremely fragile. Just using the string also means the subscriber would survive a class rename, which is if anything more likely than changing the string.

mikeryan’s picture

@catch: I see your point, but addressing the event constant class pattern seems out-of-scope here - that's been the practice throughout core, if we are to change it that should be an issue of its own.

I'm going to resubmit the tests on the patch as originally committed (#144) - if those pass, can we get this in?

mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

Oops - I saw #2796953: [regression] Plugins extending from classes of uninstalled modules lead to fatal error during discovery was committed and confused it with #2776235: Cached autoloader misses cause failures when missed class becomes available, which is the issue we've been waiting on here, and which has not been committed.

Given it seems like RC2 is imminent and we really want to get in there, I'm willing to go ahead with catch's answer - RTBC on the assumption the full set of tests I'm about to launch passes.

mikeryan’s picture

Version: 8.2.x-dev » 8.3.x-dev

Temporary to make it easy to launch all the 8.3.x tests.

mikeryan’s picture

Version: 8.3.x-dev » 8.2.x-dev

Didn't actually help...

mikeryan’s picture

Random bot fail on PHP 5.5/SQLite 3.8 - passed on rerun, but for some reason the red one didn't get removed. Anyway, passing all tests now...

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 165: 2485385-165.patch, failed testing.

phenaproxima’s picture

Issue tags: +Needs reroll

Looks like this is going to need a reroll for 8.2.x.

phenaproxima’s picture

Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new41.22 KB

Rerolled against 8.2.x, accounting for the changes introduced by #2684567: Requiring a migration w/ a source plugin using a generator fatals. No interdiff due to rejected hunks.

alexpott’s picture

+++ b/core/modules/content_translation/src/ContentTranslationUpdatesManager.php
@@ -95,9 +95,7 @@ public function onMigrateImport(MigrateImportEvent $event) {
-    if (class_exists('\Drupal\migrate\Event\MigrateEvents')) {
-      $events[MigrateEvents::POST_IMPORT][] = ['onMigrateImport'];
-    }
+    $events['migrate.post_import'][] = ['onMigrateImport'];

I don't think we should be making this change in this issue. We might very well decide to make a recommendation not to use events classes like this but that should be discussed in its own issue. I think we should do #2776235: Cached autoloader misses cause failures when missed class becomes available before this - so reviews there are welcome :)

mikeryan’s picture

The attached patch combines the latest patch here minus the MigrateEvents avoidance with the autoloading patch at https://www.drupal.org/node/2776235#comment-11659157, so the testbot can verify that this specific victim of the cached autoloading will be fixed by that patch.

The last submitted patch, 144: 2485385-144.patch, failed testing.

mikeryan’s picture

Now that #2776235: Cached autoloader misses cause failures when missed class becomes available is in, I'm retesting the patch #144 (the patch that was originally committed here, without any later workarounds for the related issue).

mikeryan’s picture

Status: Needs review » Needs work
Issue tags: +Needs reroll

Of course...

mikeryan’s picture

Assigned: phenaproxima » Unassigned
Status: Needs work » Needs review
Issue tags: -Needs reroll
StatusFileSize
new40.46 KB

Rerolled, I'll initiate the full set of tests.

Status: Needs review » Needs work

The last submitted patch, 180: move_highwater_field-2485385-180.patch, failed testing.

The last submitted patch, 180: move_highwater_field-2485385-180.patch, failed testing.

mikeryan’s picture

Status: Needs work » Needs review
StatusFileSize
new41.51 KB
new936 bytes
mikeryan’s picture

Status: Needs review » Reviewed & tested by the community

Hope my little reroll doesn't take away my RTBC privileges...

phenaproxima’s picture

I don't think re-rolls ever remove RTBC privileges :)

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Second time lucky...

Committed and pushed 4259a06 to 8.3.x and c0e3342 to 8.2.x. Thanks!

  • alexpott committed 4259a06 on 8.3.x
    Issue #2485385 by phenaproxima, quietone, alexpott, mikeryan, Berdir,...

  • alexpott committed c0e3342 on 8.2.x
    Issue #2485385 by phenaproxima, quietone, alexpott, mikeryan, Berdir,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

geek-merlin’s picture

wim leers’s picture