Я использую Taskqueue API для отправки нескольких электронных писем небольшими группами с mailgun. Мой код выглядит примерно так:
class CpMsg(ndb.Model):
group = ndb.KeyProperty()
sent = ndb.BooleanProperty()
#Other properties
def send_mail(messages):
"""Sends a request to mailgun's API"""
# Some code
pass
class MailTask(TaskHandler):
def post(self):
p_key = utils.key_from_string(self.request.get('p'))
msgs = CpMsg.query(
CpMsg.group==p_key,
CpMsg.sent==False).fetch(BATCH_SIZE)
if msgs:
send_mail(msgs)
for msg in msgs:
msg.sent = True
ndb.put_multi(msgs)
#Call the task again in COOLDOWN seconds
Приведенный выше код работал нормально, но, согласно документации, API Taskqueue гарантирует, что задача будет доставлена не менее один раз, поэтому задачи должны быть идемпотентными. Теперь, в большинстве случаев, это относится к приведенному выше коду, так как он получает только те сообщения, у которых свойство 'sent' равно False. Проблема состоит в том, что запросы ndb, не относящиеся к предкам, только в конечном итоге согласованы, что означает, что если задача выполняется дважды подряд, запрос может вернуть устаревшие результаты и включить только что отправленные сообщения.
Я думал о включении предка для сообщений, но так как отправленные электронные письма будут исчисляться тысячами, я волнуюсь, что может означать наличие больших групп сущностей, которые имеют ограниченную пропускную способность записи.
Должен ли я использовать предка для выполнения запросов? Или, может быть, есть способ настроить mailgun, чтобы избежать отправки одного и того же письма дважды? Должен ли я просто принять риск того, что в некоторых редких случаях несколько писем могут быть отправлены более одного раза?