Случайные ошибки 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

Как уже упоминалось, вам придется изменить свои представления, чтобы возвращать результаты из хранилища данных, когда все задачи будут выполнены.

Дайте мне знать, если у вас есть дополнительные вопросы и рады предоставить дополнительные указатели.

Другие вопросы по тегам