¿Cómo realizar operaciones que requieren OAuth en una cola de tareas de GAE?

Tengo una aplicación simple de Google App Engine que incluye una página /update que actualiza una lista de reproducción de YouTube. Se parece a esto:

 class UpdatePage(webapp2.RequestHandler): @decorator.oauth_required def get(self): update_result = self.update_playlist() ... routes = [('/update', UpdatePage), (decorator.callback_path, decorator.callback_handler())] app = webapp2.WSGIApplication(routes, debug=True) 

Funciona como se esperaba y el método update_playlist() hace su trabajo, pero resulta que, en algunas circunstancias, puede ejecutarse por un tiempo bastante largo, lo que resulta en un DeadlineExceededError . Entonces, después de leer acerca de las opciones disponibles, pensé que la API de la cola de tareas es el camino a seguir (¿verdad?) Y estoy intentando usarla, siguiendo la guía de Uso de colas de inserción en Python .

→ En resumen, UpdatePage en UpdatePageHandler + UpdatePageWorker :

 class UpdateHandlerPage(webapp2.RequestHandler): @decorator.oauth_required def get(self): taskqueue.add(url='/updateworker') class UpdateWorkerPage(webapp2.RequestHandler): def post(self): update_result = self.update_playlist() ... routes = [('/update', UpdateHandlerPage), ('/updateworker', UpdateWorkerPage), (decorator.callback_path, decorator.callback_handler())] app = webapp2.WSGIApplication(routes, debug=True) 

Desafortunadamente, después de hacer la división, parece que mi decorador OAuth2 ya no cumple su función:

 INFO 2013-05-30 17:08:53,971 discovery.py:709] URL being requested: https://www.googleapis.com/youtube/v3/playlists?alt=json&part=snippet%2Cstatus WARNING 2013-05-30 17:08:53,975 urlfetch_stub.py:480] Stripped prohibited headers from URLFetch request: ['content-length'] INFO 2013-05-30 17:08:54,351 client.py:493] Refreshing due to a 401 INFO 2013-05-30 17:08:54,361 appengine.py:276] make: Got type  INFO 2013-05-30 17:08:54,363 appengine.py:289] validate: Got type  INFO 2013-05-30 17:08:54,364 client.py:680] Refreshing access_token INFO 2013-05-30 17:08:54,746 client.py:699] Failed to retrieve access token: { "error" : "invalid_grant" } INFO 2013-05-30 17:08:54,757 appengine.py:276] make: Got type  INFO 2013-05-30 17:08:54,759 appengine.py:289] validate: Got type  INFO 2013-05-30 17:08:54,761 appengine.py:289] validate: Got type  INFO 2013-05-30 17:08:54,762 appengine.py:265] get: Got type  

Y si en lugar de decorar UpdateHandlerPage:get I decore UpdateWorkerPage:post , obtengo un bucle de falla infinito en su lugar:

 INFO 2013-05-30 17:24:31,307 discovery.py:190] URL being requested: https://www.googleapis.com/discovery/v1/apis/youtube/v3/rest?userIp=127.0.0.1 INFO 2013-05-30 17:24:34,960 dev_appserver.py:3105] "GET /update HTTP/1.1" 200 - INFO 2013-05-30 17:24:35,060 dev_appserver.py:3105] "POST /updateworker HTTP/1.1" 302 - WARNING 2013-05-30 17:24:35,065 taskqueue_stub.py:1980] Task task1 failed to execute. This task will retry in 0.100 seconds INFO 2013-05-30 17:24:35,240 dev_appserver.py:3105] "POST /updateworker HTTP/1.1" 302 - WARNING 2013-05-30 17:24:35,245 taskqueue_stub.py:1980] Task task1 failed to execute. This task will retry in 0.200 seconds ... 

¿Que puedo hacer? ¡Gracias por tu ayuda!

Debido a que su tarea generará la tarea Cola de tareas, no se enviará ninguno de los encabezados de su solicitud original. En particular, el encabezado de las Cookies identifica a su usuario a través de la cookie SACSID para su aplicación (proporcionada por la API de usuarios de App Engine).

ACTUALIZACIÓN: (Esto se agregó después de la publicación original). Como resultado de no tener cookies, la cookie SACSID identifica al usuario no estará allí, por lo tanto, la designación decorator.oauth_required forzará una redirección (que es HTTP 302 ) CADA vez que Se ejecuta el trabajo cron.

En lugar de intentar obtener el usuario actual del decorador, es mejor que pase el ID de usuario de App Engine a su tarea. Primero obtenga el usuario actual (dentro de su método decorado):

 from google.appengine.api import users # Guaranteed not to be None by the decorator current_user = users.get_current_user() 

y luego pasar el ID de usuario de App Engine en la tarea

 import urllib query_string = urllib.urlencode({'user_id': current_user.user_id()}) taskqueue.add(url='/updateworker?' + query_string) 

Luego, dentro de su tarea, puede recuperar ese user_id

 # This is the 'user_id' you appended in the query string user_id = self.request.get('user_id') 

y úselo para obtener las credenciales de ese usuario como se hace en el decorador :

 from oauth2client.appengine import CredentialsModel from oauth2client.appengine import StorageByKeyName # This assumes you are using the defaults for OAuth2Decorator, # which your above code is credentials = StorageByKeyName( CredentialsModel, user_id, 'credentials').get()