Problem/Motivation

From #3265086-64: Implement statement classes using \Iterator to fix memory usage regression and prevent rewinding

Drupal\migrate\Plugin\migrate\source\SourcePluginBase::rewind() is rewinding database statements

  /**
   * Rewinds the iterator.
   *
   * Implementation of \Iterator::rewind() - subclasses of SourcePluginBase
   * should implement initializeIterator() to do any class-specific setup for
   * iterating source records.
   */
  #[\ReturnTypeWillChange]
  public function rewind() {
    $this->getIterator()->rewind();
    $this->next();
  }

which is a no-op in core currently, but will be changed to throw exceptions as database statement cannot be rewound.

Steps to reproduce

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

Comments

mondrake created an issue. See original summary.

alexpott’s picture

Status: Active » Needs review
StatusFileSize
new688 bytes

Fixing the test to not result in a rewind is simple. See patch attached. This happens because we try to re-run the migration using an existing migration object...

alexpott’s picture

So the only reason \Drupal\Tests\migrate\Kernel\TrackChangesTest was passing before we merged #3174662: Encapsulate \PDOStatement instead of extending from it was because migrate kernel tests are using sqlite as the source database and StatementPrefetch::rewind() no-ops. If they'd used another db engine the test would fail. And funnily enough the test is actually bogus because it does not run again here in HEAD. Because later in the test it does

    // Execute migration again.
    $this->executeMigration('track_changes_test');

To really re-run the migration as it's now made changes that would affect the result of running the migration.

alexpott’s picture

#3 leads me to the conclusion that a hard break in \Drupal\Core\Database\StatementPrefetch::rewind() is preferable as it means that tests in contrib and custom will break if they really on the no-op and this is a good thing because it hides incorrect asssumptions.

alexpott’s picture

StatusFileSize
new2.87 KB
new1.25 KB

Here's an even better fix than #2 and that would allow us to do #3265086-62: Implement statement classes using \Iterator to fix memory usage regression and prevent rewinding and add a rewind test to prove all db drivers do the same no-op funkyness.

Include a patch that has this + what I think we should do on #3265086: Implement statement classes using \Iterator to fix memory usage regression and prevent rewinding

alexpott’s picture

StatusFileSize
new907 bytes
new1.9 KB

LOL \Drupal\migrate\Plugin\migrate\source\SqlBase::rewind() is even more broken than we thought... it also does not account for batches...

alexpott’s picture

StatusFileSize
new607 bytes
new1.9 KB

Here's a test only patch to prove that we're testing the rewind here.

Also re-upping #6 to keep it the last patch on the issue.

The last submitted patch, 7: 3339373-6.test-only.patch, failed testing. View results

andypost’s picture

+++ b/core/modules/migrate/tests/src/Kernel/TrackChangesTest.php
@@ -143,7 +143,7 @@ public function testTrackChanges() {
-    $this->executeMigration('track_changes_test');
+    $this->executeMigration($this->migration);

There's second place where executeMigration() is called and both places are suppose to instantiate migration from scratch, maybe it needs other test for rewind()?

alexpott’s picture

@andypost - yes and now we've fixed the rewind bug doing $this->executeMigration($this->migration); works whereas before for the second execution we had to do $this->executeMigration('track_changes_test'); - this is exactly what the test only patch shows.

I.e. "suppose to instantiate migration from scratch" is not correct - we don't need to re-create the migrate plugin to re-execute now that this patch has fixed \Drupal\migrate\Plugin\migrate\source\SqlBase::rewind() is fixed.

andypost’s picture

Status: Needs review » Reviewed & tested by the community

Ah sure, it exactly ensures for duplicates!

Nit: could use to extend comment to point that we call it again to make sure rewind() works, OTOH there's git blame

alexpott’s picture

Further info. In HEAD the test does

    // Save the original hash, rerun the migration and check that the hashes
    // are the same.
    $id_map = $this->migration->getIdMap();
    for ($i = 1; $i < 5; $i++) {
      $row = $id_map->getRowBySource(['tid' => $i]);
      $original_hash[$i] = $row['hash'];
    }
    $this->executeMigration($this->migration);
    for ($i = 1; $i < 5; $i++) {
      $row = $id_map->getRowBySource(['tid' => $i]);
      $new_hash[$i] = $row['hash'];
    }
    $this->assertEquals($original_hash, $new_hash);

But the $this->executeMigration($this->migration); silently fails do anything - and the test is not actually testing what it thinks it is. With the change in #6 it finally is.

At the moment all the testing is pretty implicit and we could add something more explicit if we like. That said all is very edge case and the changed test is in the correct location so leaving at RTBC.

  • catch committed 1a9665ac on 10.1.x
    Issue #3339373 by alexpott, andypost, mondrake: Drupal\migrate\Plugin\...

  • catch committed 533b9483 on 10.0.x
    Issue #3339373 by alexpott, andypost, mondrake: Drupal\migrate\Plugin\...
catch’s picture

Version: 10.1.x-dev » 10.0.x-dev
Status: Reviewed & tested by the community » Fixed

Good find. Given the test-only patch fails I think this is enough new coverage, and it unblocks the other issue. Committed/pushed to 10.1.x and cherry-picked to 9.5.x, thanks!

andypost’s picture

It was not pushed to 9.5.x for reason?

catch’s picture

Version: 10.0.x-dev » 9.5.x-dev
Status: Fixed » Reviewed & tested by the community

That was a typo, I only meant to cherry-pick to 10.0.x, however it makes sense to backport to 9.5.x if 9.5.x tests pass.

However we've also got patch releases today, so will move back to RTBC and cherry-pick once those are out.

catch’s picture

Status: Reviewed & tested by the community » Fixed

Cherry-picked to 9.5.x.

  • catch committed 5421bfe2 on 9.5.x
    Issue #3339373 by alexpott, andypost, mondrake: Drupal\migrate\Plugin\...

Status: Fixed » Closed (fixed)

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