Светлячный Dev Лог

Mon 26 December 2011

Исправление работы django-kombu с InnoDB

Tags: python

Наверное многие из вас используют django-celery, или хотя бы слышали про этот инструмент для асинхронного выполнения задач. В самом простейшем случае, когда нет желания взводить дополнительные redis или AMQP сервера, очередь задач организуется через уже имеющуюся базу данных. В моем случае это был MySQL.

В случае, когда очередь организуется через базу, Celery использует специальный бэкенд django-kombu, который устроен довольно просто — при добавлении сообщения, оно сериализуется и кладется в табличку БД, при операции pop, запись из базы изымается. Такой вот AMQP для бедных.

by weelakeo@flickr

Итак, я использовал MySQL и celery работал отлично до тех пор, пока не было принято решение сконвертировать все таблички в InnoDB дабы использовать транзакции. После такого изменения, celery перестал "подхватывать" новые задачи и выполнял их только после рестарта.

В интернетах предлагалось три решения этой проблемы:

Объясню, почему все три никуда не годятся.

Пришлось лезть в кишки django-kombu и править все самому. Оказалось, что по время опроса очереди, библиотека держит коннект с базой открытым и все селекты выполняются в рамках одной длиииной трензакции. Это означает, что все сообщения, которые будут добавлены в очередь в процессе, kombu не увидит из за того, что в MySQL по умолчанию установлен ISOLATION LEVEL REPEATABLE READ.

В итоге, я обернул несколько методов в декоратор commit_on_success, и всё заработало как надо. При этом небольшой тест показал производительность в 3 раза больше чем у версии с "грязным" хаком.

Попутно поправил еще один баг, связанный с тем, что celery завершала свою работу в случае, когда MySQL становился недоступен.

Создал Pull Request, но пока его не смерджили, исправления в моей ветке на GitHub.

Comments !