Случайные ошибки DeadlineExceeded при использовании Google Classroom API
У меня есть приложение, работающее на GAE (Python), где пользователь Google Classroom может импортировать свои курсы (имя и список студентов). Код разделен на две части. Сначала я получаю список всех курсов для этого пользователя:
directoryauthdecorator = OAuth2Decorator(
approval_prompt='force',
client_id='my_client_id',
client_secret='my_client_secret',
callback_path='/oauth2callback',
scope=[
'https://www.googleapis.com/auth/classroom.courses',
'https://www.googleapis.com/auth/classroom.rosters'])
class ClassroomAPI(webapp.RequestHandler):
@directoryauthdecorator.oauth_required
def get(self):
function=self.request.get('function')
auth_http = directoryauthdecorator.http()
service = build("classroom", "v1", http=auth_http)
if function == "getAllCourses":
try:
results = service.courses().list(pageSize=100,teacherId=users.get_current_user().email(),courseStates="ACTIVE").execute()
courses = results.get('courses',[])
#PARSE AND RETURN LIST OF COURSES TO USER
except errors.HttpError, error:
#RETURN ERROR
application = webapp.WSGIApplication(
[('/classroomAPI', ClassroomAPI),
(directoryauthdecorator.callback_path, directoryauthdecorator.callback_handler())],
debug=True)
Эта часть работает все время. Затем пользователь выбирает, какие курсы он / она хочет импортировать из списка. Выбранные курсы отправляются обратно в сценарий выше, и следующая часть выполняется:
if function == "getStudentListForCourse":
students=[]
selectedCourses = json.loads(self.request.body)["courses"]
for course in selectedCourses:
page_token=None
while True:
params={}
params["courseId"]=course["classroomId"]
params["pageSize"]=50
if page_token:
params["pageToken"]=page_token
studentList = service.courses().students().list(**params).execute()
for student in studentList['students']:
students.append(student['profile']['emailAddress'])
page_token = studentList.get('nextPageToken')
if not page_token:
break
#RETURN STUDENTS
Проблема здесь в том, что мои журналы постоянно сообщают о "DeadlineExceededError" в случайное время онлайн studentList = service.courses().students().list(**params).execute()
, что делает процесс импорта ненадежным.
Любые советы будут оценены.
ОБНОВИТЬ:
Я попробовал предложение от alpeware, но, к сожалению, это ничего не изменило.
1 ответ
В зависимости от продолжительности вашего звонка вы используете 60-секундный тайм-аут, наложенный на запросы. Вы не можете изменить это время ожидания, так как оно помогает App Engine выполнять магию масштабирования.
Чтобы обойти тайм-аут, я бы порекомендовал использовать Push-очередь как часть службы Task Queue.
Вам нужно было бы реорганизовать свой код, чтобы приспособить асинхронную загрузку списка студентов в вашем пользовательском интерфейсе и сохранить список студентов в хранилище данных.
В вашем конкретном случае вы могли бы реорганизовать свой код, чтобы использовать отложенную библиотеку для заполнения списка студентов.
Чтобы включить отложенную библиотеку, вам нужно будет внести следующие изменения в свой app.yaml
-
Добавьте следующую запись в builtins
раздел вашего app.yaml
:
- deferred: on
и следующая запись в разделе обработчиков того же файла:
- url: /_ah/queue/deferred
script: google.appengine.ext.deferred.deferred.application
login: admin
Вот кое-что, чтобы вы начали рефакторинг своего кода для использования отложенной библиотеки -
from util import getStudentList
if function == "getStudentListForCourse":
credentials = directoryauthdecorator.get_credentials()
selectedCourses = json.loads(self.request.body)["courses"]
for course in selectedCourses:
deferred.defer(getStudentList, course, credentials, None, [])
Затем создайте новый модуль util.py
-
import httplib2
from google.appengine.api import memcache
def getStudentList(course=None, credentials=None, pageToken=None, students=None):
http = httplib2.Http(cache=memcache)
auth_http = credentials.authorize(http)
service = build("classroom", "v1", http=auth_http)
params = {}
params["courseId"] = course["classroomId"]
params["pageSize"] = 50
if pageToken:
params["pageToken"] = pageToken
studentList = service.courses().students().list(**params).execute()
for student in studentList['students']:
students.append(student['profile']['emailAddress'])
pageToken = studentList.get('nextPageToken')
if pageToken:
return deferred.deferr(getStudentList, course, credentials, pageToken, students)
# There are no more students for this class.
# TODO: store students for course
Как уже упоминалось, вам придется изменить свои представления, чтобы возвращать результаты из хранилища данных, когда все задачи будут выполнены.
Дайте мне знать, если у вас есть дополнительные вопросы и рады предоставить дополнительные указатели.