Добавить «объект» в стек с таймерами истечения и получать уведомление, когда он истекает - PullRequest
3 голосов
/ 05 апреля 2011

Мне необходимо зарезервировать объект (JSON) в моем приложении на определенный период времени (обычно 180 секунд). В какой-то момент клиент может или не может вернуться и запросить этот объект по его ключу.

Хитрость заключается в том, что мне нужно получать уведомление об истечении срока действия этого объекта, чтобы я мог вернуть его в доступный пул, если клиент еще не запросил его.

Очевидные решения заключаются виспользуйте что-то вроде временной отметки в базе данных, а затем периодический скрипт для проверки устаревших элементов, но это не самое лучшее решение.

В идеале я ищу что-то вроде memcache, которое может вызвать событие, когдасрок действия элемента истекает, конечно, есть такой продукт?

Моя текущая структура основана на python, cherrpy, mongo, memcachce, но я рад добавить к нему.

Ответы [ 3 ]

1 голос
/ 24 января 2014

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

Чтобы упростить саму очистку, рассмотрите возможность создания списка кортежей (expire_time, object) и используйте bisect.insort () , чтобы упорядочить список по первому значению -время истечения:

que_tuple = (time.time() + EXPIRY_DELAY, obj)
bisect.insort(my_list, que_tuple)

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

time_to_act, obj = my_list[0]
while time.time() > time_to_act:
    return_to_pool( obj )   # whatever is necessary to clean-up your objects
    my_list.pop(0)
    time_to_act, obj = my_list[0]

Если вы решите, что вам нужно реализовать таймер, эта концепция очереди все равно будет полезна.В противном случае вы могли бы иметь таймер для истечения срока действия каждого объекта.Часто имеется ограниченное количество доступных системных таймеров, и вы можете столкнуться с нехваткой ресурсов.Очередь истечения срока действия (my_list) позволяет одному таймеру объявить следующий истекающий объект, и таймер будет сброшен на новый заголовок списка.

Надеюсь, это поможет!

0 голосов
/ 05 апреля 2011

Я почти уверен, что решение по команде redis expire должно сделать все необходимое.Это просто в использовании.Вот пример использования Redis cli.

redis> HMSET myhash field1 "Hello" field2 "World"
OK
redis> HGET myhash field1
"Hello"
redis> EXPIRE myhash 180
(integer) 1
redis> HGET myhash field2
"World"
redis> HGET myhash field2 # after 180 secs
(nil)

Далее Python имеет различные опции клиента Redis. redis-natives-py предоставляет аннотацию @tevent (после = Нет, at = Нет).

Часть уведомлений

Redis не будет уведомлять вас.Может быть, в приложении есть логика, предполагающая истечение срока действия через N секунд, и да, вы можете подтвердить это в любое время с помощью недорогой команды EXISTS.Другой вариант может использовать гринлеты, чтобы следить за временем.Как будто он создает объект redis, спит в течение N секунд и просыпается, подтверждает redis и уведомляет.Я предлагаю Гринлет в основном потому, что он намного легче, чем нить Python.

0 голосов
/ 05 апреля 2011

Я бы, наверное, использовал threading.Timer для этого.Объект Timer будет вызывать указанную функцию с заданными аргументами через определенный промежуток времени.Поэтому напишите функцию, которая возвращает объект JSON в пул, и запустите таймер, который указывает конкретный объект JSON, который был зарезервирован.Кроме того, вы можете отменить таймер до его запуска, что вы захотите сделать, если клиент действительно запрашивает объект до истечения срока резервирования.

Чтобы отслеживать пул, я бы, вероятно, использовал dictгде объект JSON является ключом, а значение равно None, если объект не извлечен, или экземпляр Timer, если он извлечен.Отдельный list может использоваться для отслеживания того, какой объект должен быть выдан следующим;pop() с конца списка при извлечении объекта и append() при его возврате.Остерегайтесь возможных условий гонки, обновляющих обе эти структуры!

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