Я работаю над системой, которая должна обрабатывать ряд условий гонки при выполнении заданий на нескольких рабочих машинах.Выполнение атомного обновления первого экземпляра в QuerySet
Клиенты будут запрашивать систему для заданий со статусом = '0' (ToDo), затем атомным способом обновить «старую» строку с статусом = «1» (заблокировано) и получить идентификатор для этого строка (для обновления задания с информацией о работнике, как то, какая машина работает над ней и т. д.).
Основная проблема здесь в том, что одновременно может быть обновлено несколько клиентов. Решение заключалось бы в блокировке около 20 строк со статусом = '0', обновлении самого старого и последующем освобождении всех блокировок. Я изучал TransactionMiddleware, но я не вижу, как это предотвратит из-за меня вопрос о том, что самый старый из них обновлен после запроса.
Я заглянул в объект QuerySet.update(), и это выглядит многообещающим, но в случае, если два клиента получат доступ к одной и той же записи, статус будет просто обновлен, и у нас будет два рабочих, работающих на той же работе .. Я действительно в недоумении.
Я также нашел билет #2705, который, кажется, отлично справляется с этим делом, но я понятия не имею, как получить код оттуда из-за моего ограниченного опыта SVN (последние обновления просто отличаются, но я не знаю, как чтобы объединить это с багажником кода).
Код: Result = Работа
class Result(models.Model):
"""
Result: completed- and pending runs
'ToDo': job hasn't been acquired by a client
'Locked': job has been acquired
'Paused'
"""
# relations
run = models.ForeignKey(Run)
input = models.ForeignKey(Input)
PROOF_CHOICES = (
(1, 'Maybe'),
(2, 'No'),
(3, 'Yes'),
(4, 'Killed'),
(5, 'Error'),
(6, 'NA'),
)
proof_status = models.IntegerField(
choices=PROOF_CHOICES,
default=6,
editable=False)
STATUS_CHOICES = (
(0, 'ToDo'),
(1, 'Locked'),
(2, 'Done'),
)
result_status = models.IntegerField(choices=STATUS_CHOICES, editable=False, default=0)
# != 'None' => status = 'Done'
proof_data = models.FileField(upload_to='results/',
null=True, blank=True)
# part of the proof_data
stderr = models.TextField(editable=False,
null=True, blank=True)
realtime = models.TimeField(editable=False,
null=True, blank=True)
usertime = models.TimeField(editable=False,
null=True, blank=True)
systemtime = models.TimeField(editable=False,
null=True, blank=True)
# updated when client sets status to locked
start_time = models.DateTimeField(editable=False)
worker = models.ForeignKey('Worker', related_name='solved',
null=True, blank=True)
Спасибо Энтони, это отличная помощь. Я попробую это сразу. – Paddie