Как передать любой объект службы API Google отложенной задаче в App Engine?

В настоящее время я разрабатываю приложение App Engine с использованием API Drive v3, но этот вопрос относится к большинству API Google.

Поскольку Drive API работает медленно в некоторых операциях, я хочу разделить каждую обработку файлов на разные задачи. Для этого я использую отложенную библиотеку, чтобы избежать сериализации-десериализации параметров.

Основным параметром является уже авторизованный служебный объект Drive API (с использованием служебных учетных записей и полномочий на уровне домена) для данного пользователя.

Упрощенный фрагмент кода выглядит так:

class Main(webapp2.RequestHandler):

    def get(self):

        # Authorize and get the Drive service 
        service = get_drive_service(keyfile, '[email protected]')

        # Iterate through all the (previously retrieved) file list
        for file_id in file_list:
            # Queue a new task by passing the function and its arguments
            deferred.defer(test_drive_service, service, file_id)


def test_drive_service(service, file_id):

    # Do a simple Drive operation
    response = service.files().get(fileId=file_id).execute()
    print response.get('name')

и часть моего файла app.yaml:

handlers:
    - url: /_ah/queue/deferred
    script: google.appengine.ext.deferred.deferred.application
    login: admin

builtins:
    - deferred: on

Если я не использую deferred.defer() и вызываю функцию test_drive_service() напрямую, проблем не возникает, и я правильно получаю нужный файл и информацию.

Однако при использовании отложенной библиотеки возникает следующая ошибка:

HttpError: <HttpError 403 when requesting (...) returned "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.">

Моя квота в порядке, поэтому дневной лимит действительно не исчерпан.

Что может быть причиной проблемы? Есть ли другой конкретный способ правильно передать объект службы в очередь задач?

ИЗМЕНИТЬ:

В соответствии с запросом, вот мой поток аутентификации:

def get_drive_service(keyfile, user_email):
    '''Builds and returns a Drive service object authorized with the service 
    account that acts on behalf of the given user.

    @param keyfile: generated JSON containing the service account details
    @param user_email: the email of the user.
    @return: Drive API service instance
    '''
    from oauth2client.service_account import ServiceAccountCredentials

    credentials = ServiceAccountCredentials.from_json_keyfile_dict(keyfile, SCOPES)

    credentials = credentials.create_delegated(user_email)

    http = credentials.authorize(httplib2.Http())
    service = discovery.build('drive', 'v3', http=http)

    return service

Он основан на OAuth 2.0 между серверами Google. docs (раздел «Другие платформы»), и снова нормально работает при непосредственном вызове функции, а не добавлении ее в очередь задач.


person cjlallana    schedule 21.03.2017    source источник


Ответы (2)


Проблема, вероятно, в том, что service неправильно сериализуется/десериализуется. Если в десериализованном объекте службы отсутствует токен доступа, это объясняет ошибку 403 Quota for unauthenticated use.

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

Я недостаточно знаю о Python в AppEngine, чтобы предложить простое решение. Я предлагаю опубликовать этот новый вопрос с тегом appengine/python/google-oauth.

Непростым решением было бы создать новую конечную точку, которую задача в очереди может вызывать для получения токена доступа.

Другим подходом было бы переместить поток авторизации в отложенную задачу. Поскольку вы используете учетную запись службы, авторизация не требует вмешательства пользователя.

person pinoyyid    schedule 21.03.2017
comment
Плохая сериализация-десериализация также была моей главной догадкой. Я нашел эти два метода в справочнике, который может иметь отношение: google.github.io/google-api-python-client/docs/epy/. Отложенная библиотека на самом деле собирает переданные параметры, поэтому я предполагаю, что эти методы вызываются внутри. Перемещение потока авторизации внутри задачи сработает, но из-за большого количества файлов будет потрачено слишком много квоты. Мне нужно было бы исследовать решение конечной точки. Возможно, сохранение и извлечение службы из хранилища данных/мемчача... - person cjlallana; 22.03.2017
comment
Это токен доступа, который вам нужно передать — memcache был бы хорошим вариантом. Опять же, я не знаком с библиотекой Python, но я надеюсь, что можно создать экземпляр службы, а затем ввести токен доступа. В любом случае убедитесь, что ваша отложенная задача может справиться с токеном доступа с истекшим сроком действия. - person pinoyyid; 22.03.2017

Превышен дневной лимит для неавторизованного использования. Для дальнейшего использования требуется регистрация

Означает, что вы не авторизованы. Вы не отправили токен доступа с запросом. Что-то не так с вашей аутентификацией.

Какую библиотеку вы используете, я думаю, вам нужно найти лучший пример учетной записи службы. Отправка файла ключа с созданием службы мне кажется неправильным.

person DaImTo    schedule 21.03.2017
comment
Спасибо за ответ, но, как я уже упоминал, служба Диска работает должным образом при прямом вызове функции, но показывает ошибку при ее откладывании. Я использую функцию from_json_keyfile_dict() (в Python) для получения учетных данных, а затем для авторизации и создания службы. Я могу отредактировать вопрос, чтобы добавить этот поток авторизации, если хотите, но я не думаю, что проблема здесь. По какой-то причине внутренняя сериализация-десериализация, выполненная отложенной библиотекой, не аутентифицирует пользователя/службу. - person cjlallana; 21.03.2017
comment
Я думаю, что это хорошая идея, чтобы вы добавили свой поток авторизации. Независимо от того, что это означает, что ошибка. Вы не авторизованы. Это также может быть просто связано с тем, что вы не применяете токен доступа к запросу, который вы делаете. проверьте сервис, посмотрите, действительно ли он получает токен доступа. - person DaImTo; 21.03.2017
comment
Ок, добавил. Но, как я указывал ранее, этот поток авторизации отлично работает в любом другом сценарии, кроме этого (откладывание/использование очередей задач). - person cjlallana; 21.03.2017