我正在使用以下方法处理基于Google App Engine db.Model(see this question)的FIFO队列。
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
此队列按预期工作(非常好)。
现在我的代码有一个方法可以访问由延迟队列调用的这个FIFO队列:
def deferred_worker():
data= QueueItem.pop()
do_something_with(data)
我想增强此方法和队列数据结构,添加一个client_ID参数,表示需要访问其自己的队列的特定客户端。 类似的东西:
def deferred_worker(client_ID):
data= QueueItem_of_this_client_ID.pop() # I need to implement this
do_something_with(data)
如何将队列编码为client_ID识别?
约束:
- 客户端数量是动态的,而不是预定义的
- Taskqueue不是一个选项(1.十个最大队列2.我想完全控制我的队列)
您知道如何使用新的Namespaces api添加此行为(请记住,我没有从webapp.RequestHandler调用db.Model)?
另一种选择:我可以在QueueItem中添加一个client_ID db.StringProperty
,它有一个pull方法的过滤器:
QueueItem.all(keys_only=True).filter(client_ID=an_ID).order('created').fetch(10)
有更好的主意吗?
答案 0 :(得分:1)
假设您的“客户端类”实际上是客户端调用的请求处理程序,您可以执行以下操作:
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.')
或者,您也可以设置名称空间app-wide。
通过设置默认命名空间,对数据存储区的所有调用都将位于该命名空间内,除非您另行明确指定。请注意,要获取并运行任务,您必须知道命名空间。因此,您可能希望在默认命名空间中维护一个名称空间列表以进行清理。
答案 1 :(得分:1)
正如我在回答您对原始答案的查询时所说的那样,您无需执行任何操作来使用命名空间:构建队列的数据存储区已经支持命名空间。只需根据需要设置命名空间,如the docs。
中所述