Pull to refresh
11
0
Станислав Борисович Ларионов @sam0delkin

User

Send message

Статья однозначно интересная. Но я такие проблемы просто решаю очередями. То есть есть основное приложение, есть консьюмеры очередей. Если нужно сделать какую-то задачу через очередь синхронно ( с блокированием потока приложения), то это делается через RPC. То есть создаётся временная эксклюзивная очередь (читать из неё может только создатель, и живёт она до конца соединения). После этого в какую-то стандартную очередь отправляется сообщение для выполнения конкретной задачи, с пометкой - ответь мне вот в эту временную очередь. Дальше основное приложение уходит в цикл и ждёт ответа (естественно, с ограничением по таймауту). В это время любой свободный консьюмер принимает сообщение, выполняет обработку и отправляет ответ во временную очередь.

Если нужно сделать какую-то большую работу, как с блокировкой, так и без, то можно воспользоваться неким подобием map-reduce. Для примера, возьмём Вашу задачу с экспортом таблицы из БД. Также нужна временная очередь, но уже не эксклюзивная. Для начала я получаю только ИД всех строк в таблице, после этого делю на кусочки по какому-нибудь BATCH_SIZE, скажем 500. И каждый такой кусочек (только ИД) посылаю в очередь. Если нужно сохранять порядок, то посылаю ещё и порядковый номер. В конце посылаю сообщение на обработку всех результатов (в нём указывается сколько было всего этих кусочков). Каждый кусочек обрабатывается консьюмером (как SELECT * FROM table WHERE id IN (:ids) , если нужно сохранять порядок, то добавляем ещё и ORDER BY). и результат пишется куда-то во временное хранилище (ключ-значение). Во временную очередь отправляется имя ключа во временном хранилище. После обработки всех кусочков очередь доходит до обработки всех значений. Но там нужна дополнительная логика. Мы каждый раз смотрим количество сообщений во временной очереди, и если оно меньше ожидаемого (а мы указали общее количество кусочков при отправке этого сообщения), то просто передобавляемся в очередь. Если оно равно ожидаемому, то просто достаём все сообщения из очереди, достаём из временного хранилища результат по ключу и пишем куда-то в постоянное хранилище (будь то файл, БД или что либо ещё).

Если то же самое нужно сделать с блокировкой, то просто можно в основном приложении после отправки читать сообщения из временной очереди и обрабатывать результаты, пока не получим количество результатов, равное изначальному количеству кусочков.

Консьюмеры как раз и будут здесь вашими "демонами", и их желательно перезапускать, потому что память всё равно будет течь :) Обычно это делается просто ограничением по времени работы процесса PHP, но не set_time_limit, а запоминать время начала команды и после обработки каждого сообщения смотреть, прошло ли время N. Таким образом, мы не остановим работу посреди обработки сообщения.

Про гонки Вы всё правильно написали, но я бы добавил, что если изначальное значение поля не важно для результата, то лучше его вообще не читать, а просто обновить. То есть

SELECT value FROM table WHERE ... FOR UPDATE;

UPDATE table SET value = :updatedValue WHERE ...;

будет хуже, чем

UPDATE table SET value = value + :diff WHERE ...;

А почему не используете composer? Много проблем бы решило. Консольную часть можно было писать с использованием компонента console symfony2.
да, знаю об этом. Собственно, с JsRoutingBundle идея и взята. Но ещё раз говорю, это лишь пример того, как можно использовать. И это не идеал кода.
И вообще, целью было не показать, как отвечать JSONом, а как использовать эвенты в Symfony2. Но это и один из способов именно выдавать браузеру JSON.
Конечно, без проблем. Но в данном случае, у меня есть не один тип. У меня ещё есть text, html и xml. И не изменяя тело контроллера, поменяв всего лишь аннотацию с Ajax(«json») на Ajax(«text»), Ajax(«html») или Ajax(«xml»), на выходе получается разный тип контента.
Согласен, читать просто и легко, но всё же, думаю, многим на русском читать будет проще.
Symfony 2 — это не веб фреймворк, а набор библиотек, на основе которого и был создан Symfony2 Framework. А на основе Symfony 2 даже собираются делать Drupal 8. Насколько я помню, это написано в официальном блоге Фабиена.
А вот тут есть отличный перевод документации Symfony. Жаль, что я это не нашёл, когда сам симфони изучал.
хотя, можно, конечно и статьи для новичков, типа основы идеи контейнера и инъектирования зависимостей)
основы идеологии: di, container, по-моему, уже давно должны стать основой идеологии любого фреймворка. Порог входа большой, да. Но это ничего не меняет.
Но последняя статья уже будет не от меня. Есть единомышленники.
Ну тогда ждите статью про расширение стандартного контроллера. А ещё, надеюсь, статью про репозитории доктрины.
Друзья, я не хочу, что бы вы здесь спорили! Я написал эту статью лишь для того, чтобы помочь сообществу. Я очень хочу, что бы Symfony была популярной среди разработчиков. И очень хочу, чтобы разработчики знали как под неё писать. Если кому-то она действительна интересна, то я могу написать ещё статей.
Всегда рад помочь!
А вообще, меня очень печалит, что на хабре очень мало статей о Symfony 2. Ведь framework действительно стоящий, а большинство статей либо дважды два, либо просто перевод документации. Попытался просто помочь сообществу, надеюсь кому-то это нужно.
Думаю, нет. Но ведь всё понятно, не так-ли?

Information

Rating
Does not participate
Location
Омск, Омская обл., Россия
Date of birth
Registered
Activity