Рейтинг:1

Почему пакет, инициированный в hook_install(), иногда может не обрабатываться?

флаг in

У меня есть два модуля, module_alpha и module_beta.

Оба модуля устанавливают таблицу базы данных с крючок_схема() которые они используют для отслеживания информации об опубликованных узлах. Данные заносятся в таблицу с сервисными методами, выполняемыми из крюк_узел_вставка () и крючок_node_update() крючки. Это все работает.

Но мне нужно обработать все существующие узлы, когда модуль установлен, чтобы заполнить пользовательские таблицы информацией об уже существующих опубликованных узлах.Каждый модуль реализует крючок_установить () и использует пакетный процесс для обработки всех существующих опубликованных узлов. Однако я наблюдаю странные несоответствия. Иногда пакетный процесс выполняется, иногда нет. Сценарий может работать для одного модуля, но не для другого. И все это несмотря на то, что код почти идентичен. Вот сценарии, которые я тестировал:

Метод установки модуля Альфа-модуль Бета-версия модуля
drush en MYMODULE Пакетное выполнение Пакет не выполняется
драш цим Пакет не выполняется Пакет не выполняется
Пользовательский интерфейс, включить модуль из /admin/modules Пакетное выполнение Пакетное выполнение
Пользовательский интерфейс, конфигурация синхронизации из /admin/config/development/configuration Пакетное выполнение Пакетное выполнение

Пакетное выполнение указывает, что пакет выполняется полностью, как и ожидалось, с сообщениями о ходе выполнения, и моя таблица заполнена данными. Пакет не выполняется указывает, что пакет вообще не выполняется. Сообщения об ошибках не отображаются и не сохраняются в журналах. Самое странное в этих данных то, что drush en module_alpha всегда удается и drush en module_beta всегда терпит неудачу.

Что может быть причиной того, что пакетный процесс работает в одних случаях, но не работает в других? Как я могу последовательно выполнять этот пакетный процесс во всех 4 этих методах, независимо от того, включен ли модуль через пользовательский интерфейс или drush? Честно говоря, единственный метод, который я буду использовать, это драш цим

Код:

В MYMODULE.install:

функция МОЙМОДУЛЬ_установить () {
  $batch = новый \Drupal\Core\Batch\BatchBuilder();
  $ партия
    ->setTitle(t('Массовая обработка существующих элементов.'))
    // Эта операция ссылается на другую функцию для каждого модуля.
    // В обоих случаях функция находится в MYMODULE.module, и код почти идентичен.
    ->addOperation('_MYMODULE_initialize_items', []);

  batch_set($batch->toArray());
}

В МОЙМОДУЛЬ.модуль:

функция _MYMODULE_initialize_items(&$context) {
  $batch_size = 25;
  $entity_type = 'узел';
  // Я нацеливаюсь на разные пакеты в module_alpha и module_beta.
  $bundle = 'MY_TARGET_BUNDLE';

  if (!isset($context['sandbox']['processed'])) {
    $context['sandbox']['processed'] = 0;
  }

  если (пусто($context['sandbox']['entity_ids'])) {
    $context['sandbox']['entity_ids'] = \Drupal::entityTypeManager()
      -> получить хранилище ($ тип_сущности)
      -> получить запрос ()
      ->условие('тип', $комплект)
      ->условие('статус', 1)
      ->выполнить();

    если (is_array($context['sandbox']['entity_ids'])) {
      $context['sandbox']['total'] = count($context['sandbox']['entity_ids']);
    }
  }

  если (!пусто($context['песочница']['entity_ids'])) {
    $current_batch_ids = array_slice($context['sandbox']['entity_ids'], $context['sandbox']['processed'], $batch_size);
    $current_batch_entities = \Drupal::entityTypeManager()
      -> получить хранилище ($ тип_сущности)
      ->loadMultiple($current_batch_ids);

    foreach ($current_batch_entities как $entity) {
      // Я использую разные сервисы и методы в module_alpha и module_beta.
      \Drupal::service('MYMODULE.my_service')
        ->процессЭнтити($сущность);

      $context['sandbox']['processed']++;
    }
  }

  если (!пусто($context['песочница']['всего'])) {
    $context['finished'] = $context['sandbox']['processed'] / $context['sandbox']['total'];
    $context['message'] = t('Обработано @обработано из @всего элементов.', [
      '@processed' => $context['sandbox']['processed'],
      '@total' => $context['sandbox']['total'],
    ]);
  }
  еще {
    $context['завершено'] = 1;
  }
}

Пример сервисного метода, вызываемого в пакетном процессе:

общедоступная функция processEntity (EntityInterface $entity) {
  // $this->db внедряется в службу `@database`, т.е. \Drupal::service('database');
  вернуть $this->db
    ->вставить('МОЙ МОДУЛЬ_mytable')
    ->поля([
      'entity_type' => $entity->getEntityTypeId(),
      'entity_bundle' => $entity->bundle(),
      'entity_uuid' => $entity->uuid(),
      // и т.д...
    ])
    ->выполнить();
}
leymannx avatar
флаг ne
Некоторое время назад я испытал нечто подобное и нашел мало информации о DO. Я попытался создать несколько фиктивных терминов для `hook_install`. Это работало, когда модуль включался через пользовательский интерфейс или `drush en`. Но это не сработало, когда модуль включился во время `drush cim`. Не найдя решения, я переместил логику из `hook_install` в пользовательскую форму в конце, чтобы она запускалась вручную из пользовательского интерфейса.
leymannx avatar
флаг ne
Только что нашел этот https://www.drupal.org/project/drupal/issues/2906107. И еще вот этот https://www.drupal.org/project/currency_taxonomy/issues/3133817. Та же проблема.
sonfd avatar
флаг in
Интересно. Может ли это быть ошибкой с `drush config:import`?
leymannx avatar
флаг ne
Думаю, да. Что-то как-то не сходится. И до сих пор не распутался. Ваши модули содержат какую-либо конфигурацию?
sonfd avatar
флаг in
Нет, без конфига.
sonfd avatar
флаг in
Я голосую за то, чтобы закрыть этот вопрос, потому что теперь я думаю, что это в основном ошибка с `drush cim`. Я думаю, что мой случай, когда module_beta не объединяется с `drush en`, это просто какая-то странная ошибка пользователя с моей стороны. Выбросьте это, и проблема будет исключительно с `drush cim` https://github.com/drush-ops/drush/issues/5105
leymannx avatar
флаг ne
Не уверен, но я думаю, что вопрос может быть удален после того, как он был закрыт на некоторое время. Может быть, вы также включите этот хорошо документированный пост в проблему, а не только ссылку здесь.
sonfd avatar
флаг in
@leymannx Хороший звонок. Спасибо.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.