2012-05-18 2 views
1

Google app engine возвращает «BadRequestError: внутри транзакций разрешены только запросы предков». Что это означает в контексте кода:gql внутри транзакций

class Counter(db.Model): 
     totalRegistrations = db.IntegerProperty(default=0) 

@db.transactional 
def countUsers(): 
    counter = Counter.all().get() 
    counter.totalRegistrations = counter.totalRegistrations + 1 
    counter.put() 
    i = counter.totalRegistrations 
    return i 

print countUsers() 
+0

Обратите внимание, что то, что вы делаете, - это своего рода анти-шаблон: имея единый объект, который вам нужно обновить, вы ограничиваете число вызывающих абонентов этим кодом примерно до 1QPS. Кроме того, вы должны использовать имена ключей, чтобы избежать необходимости запроса в первую очередь. Кроме того, никогда не используйте 'print' в webapp. –

+0

Привет, Ник, спасибо за комментарий. Не могли бы вы объяснить, что вы подразумеваете под «использовать имена ключей, чтобы избежать необходимости в запросе». Я понимаю, что этот код создаст шею для бутылок GAE, но как вы пришли к ограничению 1QPS? Спасибо. – Andrew

+0

Если у вас есть только один счетчик, вы можете указать имя ключа при его создании. THen, используйте 'Counter.get_by_key_name' внутри транзакции с указанным вами именем, избегая необходимости в запросе. Предел 1QPS - это документированная нижняя граница количества транзакций, которые вы можете ожидать от одной группы сущностей. Введение такого рода узкое место в ваше приложение - очень плохая идея. –

ответ

3

Это просто означает, что запрос запуска с Counter.all().get() не является запрос предка. В этом случае, вы должны принять запрос, который извлекает счетчик из транзакционной методы, например:

@db.transactional 
def incrementUsers(counterKey): 
    counter = Counter.get(counterKey) 
    counter.totalRegistrations = counter.totalRegistrations + 1 
    counter.put() 
    return counter.totalRegistrations 

counterKey = Counter.all(keys_only=True).get() 

print incrementUsers(counterKey) 

Это означает, что сначала нужно получить ссылку на счетчик, но только получить и поместить значение в транзакционном метод, гарантирующий атомарность.

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