Cómo implementar una cola FIFO que admite espacios de nombres

Estoy utilizando el siguiente enfoque para manejar una cola FIFO basada en db.Model de Google App Engine ( consulte esta pregunta ).

from google.appengine.ext import db from google.appengine.ext import webapp from google.appengine.ext.webapp import run_wsgi_app class QueueItem(db.Model): created = db.DateTimeProperty(required=True, auto_now_add=True) data = db.BlobProperty(required=True) @staticmethod def push(data): """Add a new queue item.""" return QueueItem(data=data).put() @staticmethod def pop(): """Pop the oldest item off the queue.""" def _tx_pop(candidate_key): # Try and grab the candidate key for ourselves. This will fail if # another task beat us to it. task = QueueItem.get(candidate_key) if task: task.delete() return task # Grab some tasks and try getting them until we find one that hasn't been # taken by someone else ahead of us while True: candidate_keys = QueueItem.all(keys_only=True).order('created').fetch(10) if not candidate_keys: # No tasks in queue return None for candidate_key in candidate_keys: task = db.run_in_transaction(_tx_pop, candidate_key) if task: return task 

Esta cola funciona como se espera (muy bien).

Ahora mismo mi código tiene un método que accede a esta cola FIFO invocada por una cola diferida:

 def deferred_worker(): data= QueueItem.pop() do_something_with(data) 

Me gustaría mejorar este método y la estructura de datos de la cola agregando un parámetro client_ID que representa a un cliente específico que necesita acceder a su propia cola. Algo como:

 def deferred_worker(client_ID): data= QueueItem_of_this_client_ID.pop() # I need to implement this do_something_with(data) 

¿Cómo podría codificar la cola para que sea consciente de client_ID?

Restricciones:
– El número de clientes es dynamic y no predefinido.
– Taskqueue no es una opción (1. diez colas máx. 2. Me gustaría tener control total en mi cola)

¿Sabes cómo puedo agregar este comportamiento utilizando la nueva API de espacios de nombres (Recuerda que no estoy llamando a la db.Model desde una aplicación web.RequestHandler)?
Otra opción: yo podría agregar un client_ID db.StringProperty a QueueItem usando un filtro en el método de extracción:

 QueueItem.all(keys_only=True).filter(client_ID=an_ID).order('created').fetch(10) 

¿Alguna idea mejor?

Suponiendo que su “clase de cliente” es realmente un controlador de solicitudes que el cliente llama, podría hacer algo como esto:

 from google.appengine.api import users from google.appengine.api.namespace_manager import set_namespace class ClientClass(webapp.RequestHandler): def get(self): # For this example let's assume the user_id is your unique id. # You could just as easily use a parameter you are passed. user = users.get_current_user() if user: # If there is a user, use their queue. Otherwise the global queue. set_namespace(user.user_id()) item = QueueItem.pop() self.response.out.write(str(item)) QueueItem.push('The next task.') 

Alternativamente, también puede establecer el espacio de nombres en toda la aplicación .

Al establecer el espacio de nombres predeterminado, todas las llamadas al almacén de datos estarán “dentro” de ese espacio de nombres, a menos que especifique explícitamente lo contrario. Solo tenga en cuenta que para obtener y ejecutar tareas, deberá conocer el espacio de nombres. Por lo tanto, es probable que desee mantener una lista de espacios de nombres en el espacio de nombres predeterminado para fines de limpieza.

Como dije en respuesta a su consulta en mi respuesta original, no necesita hacer nada para que esto funcione con espacios de nombres: el almacén de datos, en el que se crea la cola, ya admite espacios de nombres. Simplemente configure el espacio de nombres como desee, como se describe en los documentos .