From 0108a04809335eb15d37a1ab7b95fa54e3f44375 Mon Sep 17 00:00:00 2001 From: Josep Cugat Date: Wed, 22 Apr 2020 16:11:57 +0200 Subject: [PATCH] Avoid empty set on multi_cached The multi_cached decorator was always writing in the cache the result of the function, even if it was empty. This was causing the following error inside aioredis: ERROR aiocache.decorators:decorators.py:370 Couldn't set {}, unexpected error Traceback (most recent call last): File "/Users/josepcugat/workspace/aiocache/aiocache/decorators.py", line 367, in set_in_cache ttl=self.ttl, File "/Users/josepcugat/workspace/aiocache/aiocache/base.py", line 61, in _enabled return await func(*args, **kwargs) File "/Users/josepcugat/workspace/aiocache/aiocache/base.py", line 45, in _timeout return await asyncio.wait_for(func(self, *args, **kwargs), timeout) File "/Users/josepcugat/.pyenv/versions/3.6.8/lib/python3.6/asyncio/tasks.py", line 358, in wait_for return fut.result() File "/Users/josepcugat/workspace/aiocache/aiocache/base.py", line 75, in _plugins ret = await func(self, *args, **kwargs) File "/Users/josepcugat/workspace/aiocache/aiocache/base.py", line 300, in multi_set await self._multi_set(tmp_pairs, ttl=self._get_ttl(ttl), _conn=_conn) File "/Users/josepcugat/workspace/aiocache/aiocache/backends/redis.py", line 24, in wrapper return await func(self, *args, _conn=_conn, **kwargs) File "/Users/josepcugat/workspace/aiocache/aiocache/backends/redis.py", line 140, in _multi_set await _conn.mset(*flattened) File "/Users/josepcugat/.pyenv/versions/3.6.8/envs/aiocache/lib/python3.6/site-packages/aioredis/util.py", line 52, in wait_ok res = await fut aioredis.errors.ReplyError: ERR wrong number of arguments for 'mset' command --- aiocache/decorators.py | 2 +- tests/acceptance/test_decorators.py | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/aiocache/decorators.py b/aiocache/decorators.py index 9b87e6c7..b0174074 100644 --- a/aiocache/decorators.py +++ b/aiocache/decorators.py @@ -328,7 +328,7 @@ async def decorator( result = await f(*new_args, **kwargs) result.update(partial) - if cache_write: + if result and cache_write: if aiocache_wait_for_write: await self.set_in_cache(result, f, args, kwargs) else: diff --git a/tests/acceptance/test_decorators.py b/tests/acceptance/test_decorators.py index 188ab12b..c9d96954 100644 --- a/tests/acceptance/test_decorators.py +++ b/tests/acceptance/test_decorators.py @@ -1,7 +1,6 @@ import asyncio import pytest import random - from unittest import mock from aiocache import cached, cached_stampede, multi_cached @@ -110,6 +109,18 @@ async def test_multi_cached(self, cache): for key in default_keys: assert await cache.get(key) is not None + @pytest.mark.asyncio + async def test_multi_cached_with_empty_dict(self, mocker, cache): + mocker.spy(cache, "set") + + @multi_cached("keys") + async def fn(keys): + return {} + + await fn([pytest.KEY]) + assert await cache.exists(pytest.KEY) is False + assert cache.set.call_count == 0 + @pytest.mark.asyncio async def test_keys_without_kwarg(self, cache): @multi_cached("keys")