2012-05-07 2 views
0

У меня есть модель (PurchaseOrder - сокращенно PO), удерживающая бюджет времени. Пользователи могут добавлять записи часов в этот бюджет, где каждый час записывает оставшийся бюджет.Django 1.1 Signals - Незначительная проблема с синхронизацией с нитью

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

def update_po_remaining_value(sender, instance, **kwargs): 
    CalculatePOThread(sender, instance).start() 
post_save.connect(update_po_remaining_value, sender=HourRecord)  
post_delete.connect(update_po_remaining_value, sender=HourRecord) 

Нити CalculatePOThread вычисляет оставшееся значение бюджета PO через получение набора часа записи и вычитание общего час рекорда из бюджета

hr_set = HourRecord.objects.filter(purchase_order = po) 

На моем dev.workspace это работает прекрасно. В производстве соединение post_save также отлично работает, но я испытываю странную проблему с сигналом post_delete. Часто бывает так, что сумма часов, возвращаемых запросом HourRecord.objects.filter (purchase_order = po), по-прежнему включает в себя удаленную запись часа, которая вызвала поток CalculatePOThread.

Как бы то ни было, я обошел поведение с добавлением задержки до 6 секунд в поток перед выполнением запроса. time.sleep (6).

У кого-нибудь есть идея, почему такая ситуация может возникнуть? похоже, что сигнал post_delete запускается до того, как запись действительно удалена из базы данных ..!? Но это было бы ошибкой в ​​Django, и это было бы моим последним предположением.

ответ

1

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

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

+0

Спасибо за ваш ответ. Еще одна информация: я убедился, что я единственный, кто возится в prod.env. и запускается только один за другим - post.delete сигнал. Поэтому я заверил, что никакие другие потоки не противоречат моим тестам. Таким образом, блокировка должна быть установлена ​​командой удаления объекта, а сигнал post_delete должен запускаться только после того, как блокировка была освобождена/объект удален. Наверное, это внутреннее вещество Django, на которое я не могу влиять. PS: DB = postgres, webserver = apache. –

+0

кажется, что этот вопрос также обсуждается здесь: http://groups.google.com/group/django-haystack/browse_thread/thread/c452da9acfc04c64?pli=1 –

Смежные вопросы