Як працює пакетний API внутрішньо?


19

Днями я зіткнувся з проблемою таймауту, використовуючи міграцію, і почав цікавитись, як працює пакетний API .

Наскільки я розумію, це те, що в найпростішому вигляді ви передасте масив значень (наприклад, nids) та функцію для роботи над цими значеннями. Потім пакетний API обробляє фіксовану кількість цих значень з кожним запитом до його завершення.

Під час запуску пакету сторінка, схоже, використовує запити Ajax, щоб показати хід виконання пакетної операції (% виконано та повідомлення). Я припускаю, що він чекає, поки запит закінчиться, щоб оновити прогрес, а потім розпочати наступний запит негайно після цього?

Якщо сторінка із пакетним запитом закрита, чи припиняється обробка пакету? Чи він перезапуститься, коли знову відкриється та сама URL-адреса? Модуль міграції іноді триває, але він, ймовірно, використовує черги?

Відповіді:


40

Ось як працює партія (на основі мого розуміння)

1. Ініціалізуйте

  1. Ініціалізувати пакетну обробку. Залежно від конфігурації клієнтів (браузерів) щодо того, включений чи ні JavaScript.
  2. Клієнти, що підтримують JavaScript, ідентифікуються файлом cookie 'has_js' в drupal.js. Якщо під час сеансу роботи з веб-переглядачем поточного користувача не було відвідувано жодну сторінку з підтримкою JavaScript, повертається версія, яка не підтримує JavaScript.
  3. Якщо JavaScript увімкнено, Batch використовує ajax- запит, підтримуйте з'єднання живим протягом запиту.
  4. Якщо JavaScript не ввімкнено, Batch використовує набір метатегів у html для регулярних інтервалів оновлення, щоб підтримувати з'єднання живим протягом запиту.

(Ось так оновлюється панель прогресу щодо прогресу виконаної роботи.)

Пакетний процес

  1. Для запуску процесу Batch створює чергу і додає всі операції (функції та аргументи), які ви визначаєте в пакетному масиві, наприклад,

    $batch = array (
    'operations' => array(
      array('batch_example_process', array($options1, $options2)),
      array('batch_example_process', array($options3, $options4)),
      ),
    'finished' => 'batch_example_finished',
    'title' => t('Processing Example Batch'),
    'init_message' => t('Example Batch is starting.'),
    'progress_message' => t('Processed @current out of @total.'),
    'error_message' => t('Example Batch has encountered an error.'),
    'file' => drupal_get_path('module', 'batch_example') . '/batch_example.inc',
    );

    Крім того, він також призначає ідентифікатор партії, який є унікальним для всіх пакетів.

  2. Тепер Batch називає претензії на елементи черги по черзі та виконує функцію, визначену аргументами, визначеними в ній.

  3. Це важлива частина. Функція (Операція), яка реалізує пакетну операцію, повинна збивати дані та обробляти дані дуже ефективно, враховуючи обмеження пам'яті PHP, Час вимкнення . Якщо цього не зробити, це стане проблемою.

Днями я зіткнувся з проблемою таймауту, використовуючи міграцію, і почав цікавитись, як працює пакетний API.

Функція партії

Функції, які реалізують Batch, повинні дуже уважно сприймати наступні речі,

  • Кількість елементів у межах операцій, наприклад,

    if (!isset($context['sandbox']['progress'])) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['current_node'] = 0;
    $context['sandbox']['max'] = db_result(db_query('SELECT COUNT(DISTINCT nid) FROM {node}'));
    }
  • Обмеження кількості елементів для обробки в одному виклику функції, наприклад встановлення ліміту,

    // For this example, we decide that we can safely process 5 nodes at a time without a timeout.
    $limit = 5;
  • Оновлення процесу для післяобробки,

    // Update our progress information.
        $context['sandbox']['progress']++;
        $context['sandbox']['current_node'] = $node->nid;
        $context['message'] = t('Now processing %node', array('%node' => $node->title));
  • Повідомлення двигуна Batch, чи партія завершена чи не подобається,

    // Inform the batch engine that we are not finished,
    // and provide an estimation of the completion level we reached.
    if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
      $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
     }

Більшість вищезгаданих точок піклуються про основні пакетні операції Drupal, якщо вони пропущені у функції впровадження. Але завжди найкраще визначитись у функції реалізації

Пакетне завершення зворотного виклику

  • Це останній зворотний дзвінок, який викликається, коли визначено в пакетному масиві Зазвичай звіт про кількість оброблених тощо ...

ВІДПОВІДИ

Якщо сторінка із пакетним запитом закрита, чи припиняється обробка пакету? Чи він перезапуститься, коли той самий URL відкриється знову? Модуль міграції іноді триває, але він, ймовірно, використовує черги?

Так, в ідеалі він повинен перезапустити пакет і, як було сказано вище, він базується на функції, яку ви реалізуєте.

Щоб вирішити проблему з тимчасовим вимкненням PHP, використовуйте пакет Drush, який доступний у модулі міграції, але спочатку викопайте пакетні функції міграції та спробуйте скинути ваші дані обробки.


1
Страхітливий прохід. Я також хотів би зазначити, що пакет починає обробляти під час того, що, принаймні, користувачеві, видається "Ініціалізацією". екран. Тобто, якщо для налаштування першого елемента партії знадобиться 4 секунди та 10 секунд, тоді користувач побачить процес "Ініціалізація". протягом чотирнадцяти секунд у цьому прикладі. Це має сенс, оскільки перше екранне повідомлення, яке не є init, "завершено", яке працюватиме лише після обробки деяких. Якщо це неправильно, виправте мене!
texas-bronius

Також з мого досвіду. Якщо ви залишите сторінку, пакетна операція / фрагмент, який знаходиться в процесі, все одно буде споживати ресурси до її завершення. Він більше не знімає пакетну роботу, але завершує поточну.
Ілля Лінн

10

Якщо сторінка із пакетним запитом закрита, чи припиняється обробка пакету?

Так, це буде зупинено.

Чи він перезапуститься, коли той самий URL відкриється знову? Модуль міграції іноді триває, але він, ймовірно, використовує черги?

Як сказав Дінеш, це залежить від реалізації.

Ви повинні запустити міграцію за допомогою drush, тому що

Drush запускається в командному рядку і не підпадає під будь-які часові обмеження (зокрема, max_execution_time PHP не застосовується). Отже, коли ви запускаєте процес міграції, який працює за допомогою drush, він просто запускається і продовжує працювати, поки не буде завершено.

При запуску процесів через веб-інтерфейс застосовується PHP max_execution_time (як правило, 30 секунд, якщо не менше). Таким чином, для тривалих процесів нам потрібно використовувати API Batch, який управляє розбиттям процесу на кілька запитів. Таким чином, процес міграції почнеться, запуститься протягом 25 секунд або близько того, а потім зупиниться і дозволь Batch API видавати запит на нову сторінку, в якому процес міграції перезапускається, ad infinitum.

Отже, розуміючи це, чому Друш краще?

Це швидше

Пакетний API вводить багато накладних витрат - вимикання та повторне відкликання запитів на сторінку, процес міграції потрібно запустити знову всі необхідні конструктори, відновлювати з’єднання з базами даних і повторно запитувати і т. Д. І для часткового імпорту потрібно вибрати там, де вона припинилася - якщо перші 500 джерельних записів були імпортовані, їй потрібно знайти 501-й запис. Залежно від формату джерела та того, як він побудований, це може чи не масштабуватись - якщо ви використовуєте висоководні позначки із джерелом SQL, сам запит може усунути попередні записи та розпочатись там, де ви зупинилися. Якщо ні, то Migrate потрібно прокрутити вихідні дані, шукаючи першу не імпортовану запис. Маємо, скажімо, великий XML-файл як джерело,

Це надійніше

Запуск міграції через веб-переглядач додає ваш робочий стіл та локальне підключення до Інтернету як точки збою. Проблема з мережею, коли Batch API переходить на наступний запит сторінки, аварія браузера, випадкове закриття неправильної вкладки чи вікна можуть перервати вашу міграцію. Біг у барабані зменшує рухомі частини - ви усуваєте робочий стіл та локальне підключення до Інтернету як фактори.

Це корисніше

Якщо під час запуску в Drush щось піде не так, якщо є корисні повідомлення про помилки, ви їх побачите. Невдачі за допомогою пакетного API часто проковтуються, і все, що ви можете побачити, є абсолютно марним "Запит HTTP AJAX припиняється ненормально. Інформація про налагодження слідує. Шлях: / batch? Id = 901 & op = do StatusText: ResponseText: ReadyState: 4".

Ви можете знайти більше інформації про це тут .

Тим часом, якщо ви хочете запустити пакет, навіть якщо вікно браузера закрито, розгляньте модуль фонового процесу . У нього є підмодуль Background Batch, який виконує трюк.

Цей модуль переймає наявний пакетний API і виконує пакетні завдання у фоновому процесі. Це означає, що якщо ви залишите пакетну сторінку, завдання продовжуються, і ви можете пізніше повернутися до показника прогресу.


Нічого, використання барабану для міграції зробило величезне покращення. Мені потрібно перенестись на живий сайт, і це ставить набагато менше навантаження на систему! Дякую!
uwe

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.