Как реализовать очередь FIFO, которая поддерживает пространства имен - PullRequest
2 голосов
/ 19 октября 2010

Я использую следующий подход для обработки очереди FIFO на основе Google App Engine db.Model ( см. Этот вопрос ).

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. Я хотел бы иметь полный контроль над своей очередью)

Знаете ли вы, как я могу добавить это поведение, используя новые Пространства имен api (Запомнитьчто я не вызываю db.Model из webapp.RequestHandler)?
Другой вариант: я мог бы добавить client_ID db.StringProperty к QueueItem, используя для этого метод фильтра по запросу:

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

Есть идея получше?

Ответы [ 2 ]

1 голос
/ 19 октября 2010

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

1 голос
/ 19 октября 2010

Предполагая, что ваш "клиентский класс" действительно является обработчиком запросов, которые вызывает клиент, вы можете сделать что-то вроде этого:

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.')

В качестве альтернативы, вы также можете установить пространство имен на уровне приложения .

При установке пространства имен по умолчанию все вызовы к хранилищу данных будут «внутри» этого пространства имен, если вы явно не укажете иное.Просто отметьте, что для выборки и запуска задач вам нужно знать пространство имен.Таким образом, вы, возможно, захотите сохранить список пространств имен в пространстве имен по умолчанию для целей очистки.

...