Django, паттерн Борг, вызовы API, результаты кеширования - PullRequest
3 голосов
/ 29 июля 2010

Я использую API с другого сайта, который возвращает пару «ценовых URL-адресов, которые мои пользователи используют для покупки виртуальных товаров.

Я должен кешировать эти результаты не менее часа, так как они не сильно меняют цены в своей системе. (И мы хотим сохранить и нашу, и их пропускную способность.)

После поиска синглтонов в Python я обнаружил шаблон borg, который кажется еще круче, поэтому я сделал следующее:

def fetchPrices():
    #uses urllib2.urlopen() to fetch prices
    #parses results with ElementTree
    return prices

class PriceStore():
    __shared_state = {}

    def update(self):
        if self.lastUpdate is not None and (datetime.now() - self.lastUpdate).seconds >= 3600:
            self.prices = fetchPrices()
            self.lastUpdate = datetime.now()
        elif self.lastUpdate is not None:
            return
        else:
            self.lastUpdate = datetime.now() - timedelta(hours=1)
            self.update()

    def __init__(self):
        self.__dict__ = self.__shared_state
        self.lastUpdate = None
        self.update()

Идея заключается в следующем:

store = PriceStore()
url = store.prices['2.9900']['url']

И магазин должен правильно инициализироваться и получать только новую информацию о ценах, если существующая информация старше одного часа.

Я, кажется, сталкиваюсь с их API при каждой инициализации PriceStore. Кто-нибудь может определить мою проблему? Могу ли я использовать в django глобальную переменную, такую ​​как __shared_state, и ожидать, что она все еще будет содержать информацию о ценах?

Спасибо!

Ответы [ 3 ]

4 голосов
/ 29 июля 2010

Я, кажется, сталкиваюсь с их API каждый раз при инициализации PriceStore.Кто-нибудь может определить мою проблему?

Да, это легко определить:

def __init__(self):
    self.__dict__ = self.__shared_state
    self.lastUpdate = None

self.lastUpdate = None абсолютно гарантирует , что следующий сразу же вызов self.update() найдет значение self.lastUpdate равным None - вы просто заставили его сделать это!

Удалите это self.lastUpdate = None в __init__ и, например, используйте вместо

lastUpdate = None

на уровне тела класса , например, сразу после назначения __shared_state = {} и с тем же выравниванием, что и это назначение. Это заставит вещи работать так, как вы собираетесь.

1 голос
/ 29 июля 2010

Ваша основная проблема заключается в том, что при создании нового PriceStore вы устанавливаете self.lastUpdate в None (в вашей второй строке).Поэтому, хотя все они имеют общее состояние, каждый новый объект перекрывает состояние.

Вместо этого сделайте это:

class PriceStore():
    __shared_state = {'lastUpdate': None}

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

0 голосов
/ 29 июля 2010

В __init__ вы установите self.lastUpdate = None. Не делай этого.

В частности, рассмотрим следующий код:

A = PriceStore()

# some time later

B = PriceStore()

Теперь A.lastUpdate == Нет, чего вы не хотели! Вместо этого попробуйте

if "lastUpdate" not in self.__dict__:
    self.lastUpdate = None

Таким образом, вы никогда не перезаписываете его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...