Как избежать кеширования Django QuerySet в @staticmethod - PullRequest
2 голосов
/ 20 ноября 2010

Следующие несколько строк кода иллюстрируют распределенную рабочую модель, которую я использую для обработки данных. Задания создаются в базе данных, их данные отправляются на большие диски, и как только вся информация становится доступной, статус задания устанавливается на «ОЖИДАНИЕ». Отсюда в игру вступают несколько активных работников: время от времени каждый из них выдает запрос, в котором он пытается «претендовать» на работу. Чтобы синхронизировать заявки, запросы инкапсулируются в транзакцию, которая немедленно изменяет состояние задания, если запрос возвращает кандидата. Пока все хорошо.

Проблема в том, что запрос на претензию работает только в первый раз. Читая о QuerySets и их поведении кэширования, мне кажется, что комбинирование статических методов и кэширования QuerySet всегда возвращается к кешу ... посмотрите сами:

У меня есть класс, полученный из django.db.models.Model:

class Job(models.Model):
[...]

, в котором я определяю следующую статическую функцию.

@staticmethod
@transaction.commit_on_success
def claim():
    # select the oldest, top priority job and 
    # update its record
    jobs = Job.objects.filter(state__exact = 'WAITING').order_by('-priority', 'create_timestamp')
    if jobs.count() > 0:
        j = jobs[0]
        j.state = 'CLAIMED'
        j.save()
        logger.info('Job::claim: claimed %s' % j.name)
        return j
    return None

Есть ли очевидная вещь, которую я делаю неправильно? Что было бы лучшим способом борьбы с этим? Как я могу убедиться, что QuerySet не кэширует свои результаты при разных вызовах статического метода? Или я что-то упускаю и гоняюсь за призраком? Любая помощь будет принята с благодарностью ... Спасибо!

Ответы [ 2 ]

3 голосов
/ 20 ноября 2010

Решение оказалось очень, очень тривиальным: скорость здесь не такая уж важная проблема, вызывая

Jobs.objects.update()

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

0 голосов
/ 20 ноября 2010

Почему бы просто не иметь простой функции уровня модуля claim_jobs(), которая бы выполняла запрос?

def claim_jobs():

    jobs = Job.objects.filter(...)
    ... etc.
...