2

我正在使用以下方法来处理基于 Google App Engine db.Model 的 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?

约束:
- 客户端数量是动态的,不是预定义
的 - 任务队列不是一个选项(1. 最多十个队列 2. 我想完全控制我的队列)

您知道如何使用新的Namespaces api添加此行为(请记住,我不是从 webapp.RequestHandler 调用 db.Model)?
另一种选择:我可以添加一个client_ID db.StringProperty到 QueueItem 使用它有一个拉方法过滤器:

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

有更好的主意吗?

4

2 回答 2

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

通过设置默认命名空间,对数据存储的所有调用都将在该命名空间“内”,除非您明确指定。请注意,要获取和运行任务,您必须知道命名空间。因此,您可能希望在默认命名空间中维护一个命名空间列表以进行清理。

于 2010-10-18T23:21:15.920 回答
1

正如我在回答您对我的原始答案的询问时所说的那样,您不需要做任何事情就可以使用命名空间:构建队列的数据存储区已经支持命名空间。只需根据需要设置命名空间,如文档中所述

于 2010-10-19T09:11:18.647 回答