- Issue created by @joachim
When a batch runs to import entities, each imported entity translation is added to a list in RuntimeImportContext, which holds it in $importedEntities:
// Store data to prevent the entity of being re-imported.
$this->runtimeImportContext->addImportedEntity($processed_entity_langcode, $processed_entity_uuid);
The ImportService then checks for this to prevent an infinite loop:
// Prevent infinite loop.
// Check if we try to import an already imported entity translation.
// We can't check this in the STAGE_IS_ENTITY_IMPORTABLE stage because we
// need to obtain the entity ID to return it for entity reference fields.
$processed_entity_langcode = $processed_entity->language()->getId();
$processed_entity_uuid = $processed_entity->uuid();
if ($this->runtimeImportContext->isEntityTranslationImported($processed_entity_langcode, $processed_entity_uuid)) {
continue;
}
The problem is that the RuntimeImportContext is stored on the ImportService ( 📌 ImportService shouldn't hold stateful data in the RuntimeImportContext Active ). There's no reference to it in the BatchAPI sandbox. The list of imported entities in the current batch is added to the batch results:
$context['results']['imported_entity_ids'] = NestedArray::mergeDeep($context['results']['imported_entity_ids'], $import_service->getRuntimeImportContext()->getImportedEntities());
but that is only used to output a count to the UI at the end of the batch run.
The problem is that when the BatchAPI causes a new web request, the ImportService is re-created from the DI container, and gets a brand new RuntimeImportContext object created in its constructor. That new RuntimeImportContext won't have the $importedEntities assembled so far.
During BatchAPI operations, we can't rely on any values in code to persist, other than the batch sandbox.
So we either have to put the entity list in the sandbox (where there's a scalability issue because the sandbox is serialized and stored in a DB column), or in the database directly.
Active
4.0
Entity Share Client