Pull to refresh
12
0
Кожемякин Артём@lemark

Пользователь

Send message
Концепция довольно проста.
Когда вы устонавливаете задание для батч, задание помещается в БД.
Затем происходит переход на страницу с JavaScript кодом который начинает делать последовательные асинхронные запросы на сервер (в друпал к странице example.com/batch) передавая в качестве одного из параметров ID задания.
Сервер выполняет часть этого задания (одну операцию или одну одну итерацию) и возвращает назад либо сообщение о том что перация выполнена либо процент выполнения.

Таким образом вся магия заключается в том, что большое задание разбивается на несколько этапов и соотвествено несколько запросов, позволяя избежать при этом превышения максимального времени выполнения скрипта.
Минус всего этого заключается в том, что при закрытии страничке в браузере с выполняющимся заданием работа механизма прекращается т.к. некому становиться посылать запросы на сервер. Этот эффект можно немного смягчить, если спланировать задание так, чтобы его результат постепенно сохранялся в БД (допустим помечать обработанные ноды, чтобы ни не попали в следущее задание). Тогда можно будет когда нужно прервать задание, а потом безболезненно и без потери результатов запустить его заново.
Представьте что у Вас есть некоторый запрос $sql через который вы получаете массив nid с которыми надо что-то сделать. Тогда перед установкой батча Вы делаете count query к этому запросу получая объем выборки $total. Передаете его в качестве аргумента в операцию.

В самой операции делаете свой запрос $sql с LIMIT $a,$a+$k где
$a — то сколько вы нод уже обработали (отступ)
$k — сколько нод вы хотите обрабатывать за одну итерацию (так чтобы итерация занимала приемлимое для Вас время, например 10 секунд)

Потом идет что-то типо такого блока
if ($a + $k >= $total) {
  $context['finished'] = 1;
}
else {
// Тут сохраняем отступ и достаем его потом в начале следущей итерации
  $context['sandbox']['offset'] = $a + $k;
// Эта штука показывает прогресс. Принимает значения [0;1].
  $context['finished'] = ($a + $k) / $total;
}


Таким образом операция будет выполняться пока $context['finished'] не станет 1 при этом сообщая батчу о прогрессе после каждой итерации. Обратите внимание на то, что $context['sandbox'] не переходит между операциями.
3 коммент сверху :)
Да тут тоже очень хороший пример + разобран хорошо
api.drupal.org/api/drupal/includes--form.inc/group/batch/6
Callback операции в качестве последнего аргумента должен принимать по ссылке переменную &$context.

В принципе нет нужды как у Вас через цикл создавать отдельную операцию для каждой ноды.
Корректнее будет передать в операцию весь массив а в конце выполнения операции устанавливать значение $context['finished'] равное количеству обработанных нод деленному на общую длину массива. Прогресс можно сохранять в массиве $context['sandbox']. Операция будет автоматически вызываться до тех пор пока $context['finished'] не примет в качестве значения единицу.

Такой подход лучше
1. С точки зрения идеологии и эстетики: т.к. в батче по хорошему должна быть 1 колбэк — 1 операция (За очень редким исключением. Допустим если надо выполнить операцию А потом Б а потом сново А например)
2. С точки зрения производительности. Батч сохраняет последовательность операций в БД. А теперь представьте что у Вас рабочая ситуация и ноды достаются из БД в количестве 100500+ штук. Вот у Вас и запишется в ячейку 100500+ операций. А на самом деле нужно записать только 1.
Вот собственно с апрельской конференции video.yandex.ru/users/vaspi/view/40
Доклад от ребят из Axel Springer (Forbes) по поводу настройки окружения для Drupal под high loaded проект.
Вот собственно с апрельской конференции video.yandex.ru/users/vaspi/view/40
Доклад от ребят из Axel Springer (Forbes) по поводу настройки окружения для Drupal под high loaded проект.
Она мощна тем что логична и проста до безобразия :) Не поленитесь покопаться в коде и посмотреть как оно устроено.
В 7 уже активно используется ООП. А полного перехода на объектную модель и отказа от системы хуков и конвенциональных функций вроде как пока и в 8ке не планируется. Строго говоря я еще не видел более или менее вменяемой аргументации в пользу того что такой переход вообще нужен.
Не люблю такие статье вида «я люблю то-то за то-то» или «я не люблю это за это» т.к. они вызывают классический (и чаще всего на 80% бессмысленный и бездоказательный" срач.
Уже 3 года пишу.
Во первых нравится, а во вторых если сравнивать разработку под 7ку и под 6ку видна явная динамика в сторону улучшения качества кода.
Мда. Забавно. Спрошу в декабре на конференции почему так.
Я первый раз видел эту штуку применительно к eve online ))
www.eve-pirate.com/uploads/LearningCurve.jpg
Наверное полезная статья для тех кто о Drupal вообще не слышал.
А кто тут возмущается насчет производительности, запутанности и т.п. проконсультируйтесь с ребятами из Axel Springer. Forbes.ru один из самых загруженных ресурсов России не считая соц сетей и успешно работает на друпале. При это работает это все не на огромном кластере а на 6 серверах (2бэ+2фэ+2бд) 3 из которых являются репцлицирующими.
Окей. Создам новый бранч.

Я прогонял. Только я прогонял из меню модулей а не из меню кодера. А оттуда оно по умолчанию прогоняется на нормале. На друпалорге попросили прогнать на миноре.

Во общем исправлять там не много, завтра к вечеру думаю все исправлю.
Поискал в запросах на функционал (feature requests): drupal.org/node/1004970
Там сказано что реализовывать данный функционал в рамках модуля References не планируется, но уже есть надстройки.

drupal.org/project/nodeconnect
вот вроде то что надо
Тоже правда. На самом деле если рассматривать задачу в комплексе довольно интересно получается. Думал по этому поводу, есть такое неординарное решение.
Сделать тип поля которое бы было ссылкой на ноду.
Как будет работать:
Добавляете к материалу тип поля node_reference (назовем его так, кпримеру)
В настройках поля указываете на ноды какого типа будет ссылаться.
Также как и для любого поля можно указать чтобы количество элементов полей было N или неограничено.

Далее когда добавляете материал, можете сразу в процессе добавления этого материала, также как обычно заполняете поля, заполнить поле ассоциированных нод. После создания материала автоматически создаются эти ноды и связываются с ним. Потом также можно редактировать их либо по отдельности либо из родительского материала.

Вот такая идея. можно развить :)

Information

Rating
Does not participate
Location
Россия
Date of birth
Registered
Activity