Функции кэширования в Aiohttp-Asyncio

Я пытаюсь кэшировать функцию из aiohttp, используя memcached. Кэширование хочу сделать как декоратор. Пример вызова декоратора выглядит так:

@cache("main_page", expire=25)
@asyncio.coroutine
def page(request):
    return aiohttp_jinja2.render_template('index', request, {} )

Декоратор функции, который занимается кэшированием, выглядит так:

def cache_key(name, kwargs):
    key = b'\xff'.join(bytes(k, 'utf-8') + b'\xff' + pickle.dumps(v) for k, v in kwargs.items())
    key = bytes(hashlib.sha1(key).hexdigest(), 'ascii')
    return key


def cache(name, expire=0):
    def decorator(func):
        @asyncio.coroutine
        def wrapper(request=None, **kwargs):
            assert isinstance(request, (aiohttp.web_reqrep.Request, type(None))), type(request)
            args = [r for r in [request] if isinstance(r, aiohttp.web_reqrep.Request)]
            assert isinstance(mc, aiomcache.Client)
            key = cache_key(name, kwargs)
            value = yield from mc.get(key)
            if value is None:
                value = yield from func(*args, **kwargs)
                yield from mc.set(key, pickle.dumps(value,   protocol=pickle.HIGHEST_PROTOCOL), exptime=expire)
            else:
                value = pickle.loads(value)
            print(value)
            return value

        return wrapper

    return decorator

Но я получаю ошибку в консоли:

  File "/usr/local/lib/python3.4/dist-packages/aiohttp_debugtoolbar/panels/headers.py", line 25, in process_response
    sorted(response.headers.items())]
  File "aiohttp/_multidict.pyx", line 464, in aiohttp._multidict._ItemsView.__iter__ (aiohttp/_multidict.c:8990)
TypeError: 'NoneType' object is not iterable

Насколько я понимаю вопрос:

Как сериализовать/десериализовать Response, если возможно, а если невозможно, что делать для кеширования результата - есть какие-то обходные пути?


person alex10    schedule 02.10.2015    source источник


Ответы (1)


aiohttp не предназначен для использования в качестве кэширующего прокси-сервера, поэтому web.StreamResponse и потомки не сериализуемы.

Идея сериализации ответа потока или сеанса веб-сокета немного неудобна, не так ли? Возможно, мне следует добавить поддержку травления для мультидиктов, но у меня нет на это запроса пользователя.

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

person Andrew Svetlov    schedule 03.10.2015