Как передать данные NDB в очередь задач?

Вот объект, который я хотел бы передать задаче:

class MyData(ndb.Model):
    ...
    text = ndb.StringProperty(indexed=False)
    data = ndb.BlobKeyProperty(repeated=True)
    details = ndb.KeyProperty(kind=Details)

Могу ли я сделать что-то вроде ниже?

mydata = MyData.query()
mydata = mydata.filter(...)
mydata = mydata.order(MyData.added)
mydata = mydata.fetch(100)
for d in mydata:
  taskqueue.add(url='/worker', payload=d)

Как я могу извлечь данные из полезной нагрузки тогда? Не думайте, что self.request.get('payload') сработает. Поймите, что я могу передать только ключ ndb и прочитать сущность внутри задачи. Но это потребует дополнительных операций чтения. Или я могу как-то использовать keys_only, когда fetch(100)? keys_only операции бесплатны в соответствии с документом:

Операции с небольшими хранилищами данных включают вызовы для выделения идентификаторов хранилищ данных или запросы только на ключи, и эти операции бесплатны.

Но считаются ли они операциями чтения хранилища данных?


person LA_    schedule 30.05.2014    source источник


Ответы (2)


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

mydata = MyData.query()
mydata = mydata.filter(...)
# the order shouldn't matter, unless you want to make sure that property exists.
# mydata = mydata.order(MyData.added)   
mydata = mydata.fetch(100, keys_only=True)
tasks = [taskqueue.Task(url='/worker', params={'key': key.urlsafe()}) for key in mydata]
taskqueue.Queue('default').add(tasks)
person Josh    schedule 30.05.2014
comment
Благодарю вас! В чем преимущество однократного вызова? Я планирую использовать уникальное имя для каждой задачи (таким образом, у меня не будет повторяющейся обработки одной и той же ошибки), что произойдет с пакетным вызовом, если есть задача с повторяющимся именем? - person LA_; 31.05.2014
comment
Не могли бы вы также помочь понять, как извлечь полезную нагрузку? self.request.get('payload') пусто. - person LA_; 01.06.2014
comment
Обновлен payload до params - теперь вы будете использовать self.request.get('key'). - person Josh; 01.06.2014
comment
developers.google.com/appengine/docs/python/taskqueue/ описывает, что происходит, когда вы добавляете уже существующие задачи. Если вы беспокоитесь о повторяющихся задачах для каждого элемента, я добавляю их по одной и ловлю (taskqueue.TaskAlreadyExistsError, taskqueue.TombstonedTaskError). - person Josh; 01.06.2014
comment
Ах, да, я умею пользоваться params, но особенно интересовался payload ;) - person LA_; 01.06.2014
comment
Вы можете получить payload из self.request.body в обработчике задач. :) (полезная нагрузка - это данные POST) - person Josh; 02.06.2014
comment
Не могли бы вы опубликовать код? Идея ясна, но я не понимаю, как ее реализовать... - person LA_; 03.06.2014

d по-прежнему является объектом ndb. Чтобы передать это как словарь, попробуйте это (непроверено):

taskqueue.add(url='/worker', payload=d.to_dict())

https://developers.google.com/appengine/docs/python/ndb/modelclass#Model_to_dict

person GAEfan    schedule 30.05.2014
comment
Это не сработает, так как details является ndb.KeyProperty, который не может быть закодирован в JSON без дополнительной работы. Я бы переопределил to_dict для обработки KeyProperty и обязательно применил .urlsafe() для преобразования их в строки. Тогда у вас не возникнет проблем с получением этих сущностей позже. - person Josh; 31.05.2014