Issue #2545672 by mikeryan, benjy, phenaproxima: Handle various migration interruption scenarios
parent
2b0de9c17a
commit
8f94d83897
|
@ -458,6 +458,14 @@ class Migration extends ConfigEntityBase implements MigrationInterface, Requirem
|
|||
return \Drupal::keyValue('migrate_result')->get($this->id(), static::RESULT_INCOMPLETE);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function interruptMigration($result) {
|
||||
$this->setStatus(MigrationInterface::STATUS_STOPPING);
|
||||
$this->setMigrationResult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -206,6 +206,15 @@ interface MigrationInterface extends ConfigEntityInterface {
|
|||
*/
|
||||
public function getMigrationResult();
|
||||
|
||||
/**
|
||||
* Signal that the migration should be interrupted with the specified result
|
||||
* code.
|
||||
*
|
||||
* @param int $result
|
||||
* One of the MigrationInterface::RESULT_* constants.
|
||||
*/
|
||||
public function interruptMigration($result);
|
||||
|
||||
/**
|
||||
* Get the normalized process pipeline configuration describing the process
|
||||
* plugins.
|
||||
|
|
|
@ -298,10 +298,17 @@ class MigrateExecutable implements MigrateExecutableInterface {
|
|||
unset($sourceValues, $destinationValues);
|
||||
$this->sourceRowStatus = MigrateIdMapInterface::STATUS_IMPORTED;
|
||||
|
||||
// Check for memory exhaustion.
|
||||
if (($return = $this->checkStatus()) != MigrationInterface::RESULT_COMPLETED) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If anyone has requested we stop, return the requested result.
|
||||
if ($this->migration->getStatus() == MigrationInterface::STATUS_STOPPING) {
|
||||
$return = $this->migration->getMigrationResult();
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
$source->next();
|
||||
}
|
||||
|
|
|
@ -95,8 +95,9 @@ class MigrateEventsTest extends KernelTestBase {
|
|||
|
||||
$event = $this->state->get('migrate_events_test.map_save_event', []);
|
||||
$this->assertIdentical($event['event_name'], MigrateEvents::MAP_SAVE);
|
||||
$this->assertIdentical($event['fields']['sourceid1'], 'dummy value');
|
||||
$this->assertIdentical($event['fields']['destid1'], 'dummy value');
|
||||
// Validating the last row processed.
|
||||
$this->assertIdentical($event['fields']['sourceid1'], 'dummy value2');
|
||||
$this->assertIdentical($event['fields']['destid1'], 'dummy value2');
|
||||
$this->assertIdentical($event['fields']['source_row_status'], 0);
|
||||
|
||||
$event = $this->state->get('migrate_events_test.map_delete_event', []);
|
||||
|
@ -105,13 +106,15 @@ class MigrateEventsTest extends KernelTestBase {
|
|||
$event = $this->state->get('migrate_events_test.pre_row_save_event', []);
|
||||
$this->assertIdentical($event['event_name'], MigrateEvents::PRE_ROW_SAVE);
|
||||
$this->assertIdentical($event['migration']->id(), $migration->id());
|
||||
$this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value');
|
||||
// Validating the last row processed.
|
||||
$this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value2');
|
||||
|
||||
$event = $this->state->get('migrate_events_test.post_row_save_event', []);
|
||||
$this->assertIdentical($event['event_name'], MigrateEvents::POST_ROW_SAVE);
|
||||
$this->assertIdentical($event['migration']->id(), $migration->id());
|
||||
$this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value');
|
||||
$this->assertIdentical($event['destination_id_values']['value'], 'dummy value');
|
||||
// Validating the last row processed.
|
||||
$this->assertIdentical($event['row']->getSourceProperty('data'), 'dummy value2');
|
||||
$this->assertIdentical($event['destination_id_values']['value'], 'dummy value2');
|
||||
|
||||
// Generate a map delete event.
|
||||
$migration->getIdMap()->delete(['data' => 'dummy value']);
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\migrate\Tests\MigrateInterruptionTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\migrate\Tests;
|
||||
|
||||
use Drupal\migrate\Entity\Migration;
|
||||
use Drupal\migrate\Event\MigratePostRowSaveEvent;
|
||||
use Drupal\migrate\MigrateMessage;
|
||||
use Drupal\migrate\Entity\MigrationInterface;
|
||||
use Drupal\migrate\Event\MigrateEvents;
|
||||
use Drupal\migrate\MigrateExecutable;
|
||||
use Drupal\simpletest\KernelTestBase;
|
||||
|
||||
/**
|
||||
* Tests interruptions triggered during migrations.
|
||||
*
|
||||
* @group migrate
|
||||
*/
|
||||
class MigrateInterruptionTest extends KernelTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = ['migrate', 'migrate_events_test'];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
\Drupal::service('event_dispatcher')->addListener(MigrateEvents::POST_ROW_SAVE,
|
||||
array($this, 'postRowSaveEventRecorder'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests migration interruptions.
|
||||
*/
|
||||
public function testMigrateEvents() {
|
||||
// Run a simple little migration, which should trigger one of each event
|
||||
// other than map_delete.
|
||||
$config = [
|
||||
'id' => 'sample_data',
|
||||
'migration_tags' => ['Event test'],
|
||||
'source' => ['plugin' => 'data'],
|
||||
'process' => ['value' => 'data'],
|
||||
'destination' => ['plugin' => 'dummy'],
|
||||
'load' => ['plugin' => 'null'],
|
||||
];
|
||||
|
||||
$migration = Migration::create($config);
|
||||
|
||||
/** @var MigrationInterface $migration */
|
||||
$executable = new MigrateExecutable($migration, new MigrateMessage);
|
||||
// When the import runs, the first row imported will trigger an interruption.
|
||||
$result = $executable->import();
|
||||
|
||||
$this->assertEqual($result, MigrationInterface::RESULT_INCOMPLETE);
|
||||
|
||||
// The status should have been reset to IDLE.
|
||||
$this->assertEqual($migration->getStatus(), MigrationInterface::STATUS_IDLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reacts to post-row-save event.
|
||||
*
|
||||
* @param \Drupal\Migrate\Event\MigratePostRowSaveEvent $event
|
||||
* The migration event.
|
||||
* @param string $name
|
||||
* The event name.
|
||||
*/
|
||||
public function postRowSaveEventRecorder(MigratePostRowSaveEvent $event, $name) {
|
||||
$event->getMigration()->interruptMigration(MigrationInterface::RESULT_INCOMPLETE);
|
||||
}
|
||||
|
||||
}
|
|
@ -31,11 +31,15 @@ class DataSource extends SourcePluginBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function initializeIterator() {
|
||||
return new \ArrayIterator(array(array('data' => 'dummy value')));
|
||||
return new \ArrayIterator([
|
||||
['data' => 'dummy value'],
|
||||
['data' => 'dummy value2'],
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
public function __toString() {
|
||||
return '';
|
||||
return 'Sample data for testing';
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +54,7 @@ class DataSource extends SourcePluginBase {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function count() {
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue