Skip to content

Commit

Permalink
IAM: Replace LRU cache with one that works
Browse files Browse the repository at this point in the history
Previously, when we saved the same key multiple times
in the cache (after expiration) and we overflowed the cache,
a KeyError exception was raised.

Also, if we overflowed the cache with many different keys,
the overall cache size would only increase.
  • Loading branch information
AymericDu authored and fvennetier committed Dec 30, 2021
1 parent a64be4e commit 743942d
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 3 deletions.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
swift>=2.13.0
functools32
lxml
requests!=2.9.0,>=2.8.1 # Apache-2.0
six>=1.9.0
Expand Down
37 changes: 34 additions & 3 deletions swift3/iam.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import time
from fnmatch import fnmatchcase
from functools import wraps
from functools32 import lru_cache

from swift.common.utils import config_auto_int_value, get_logger, LRUCache
from swift.common.utils import config_auto_int_value, get_logger

from swift3.exception import IAMException
from swift3.response import AccessDenied
Expand Down Expand Up @@ -355,6 +357,30 @@ def wrapper(*args, **kwargs):
return real_check_iam_access


def tlru_cache(maxtime=30, maxsize=1000):
"""
Least-recently-used cache decorator with time-based cache invalidation.
Due to the technique used, an entry can expire before the TTL,
but never after.
"""
def tlru_cache_decorator(func):
@lru_cache(maxsize=maxsize)
def salted_func(__salt, *args, **kwargs):
return func(*args, **kwargs)

@wraps(func)
def tlru_cache_wrapper(*args, **kwargs):
# Generate an extra argument, which will be the same for
# maxtime seconds. After maxtime seconds, the argument changes,
# and thus triggers a cache miss.
return salted_func(int(time.time() / maxtime), *args, **kwargs)

return tlru_cache_wrapper

return tlru_cache_decorator


class IamMiddleware(object):
"""
Base class for IAM implementations.
Expand All @@ -368,8 +394,13 @@ def __init__(self, app, conf):
self.connection = conf.get('connection')
maxsize = config_auto_int_value(conf.get('cache_size'), 1000)
maxtime = config_auto_int_value(conf.get('cache_ttl'), 30)
self._load_rules_matcher = LRUCache(maxsize=maxsize, maxtime=maxtime)(
self._build_rules_matcher)
if maxsize > 0:
if maxtime <= 0:
maxtime = float('inf')
self._load_rules_matcher = tlru_cache(
maxsize=maxsize, maxtime=maxtime)(self._build_rules_matcher)
else:
self._load_rules_matcher = self._build_rules_matcher

def __call__(self, env, start_response):
# Put the rules callback in the request environment so middlewares
Expand Down

0 comments on commit 743942d

Please sign in to comment.