Skip to content

Commit

Permalink
cache: Simplify invalidation logic to match existing behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
iamkroot committed May 22, 2022
1 parent da6c598 commit ac5485b
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 38 deletions.
39 changes: 8 additions & 31 deletions confuse/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
class CachedHandle(object):
"""Handle for a cached value computed by applying a template on the view.
"""
# some sentinel objects
_INVALID = object()
_MISSING = object()
"""Sentinel object to denote that the cached value if out-of-date."""

def __init__(self, view: ConfigView, template=templates.REQUIRED) -> None:
self.value = self._INVALID
Expand All @@ -22,12 +21,8 @@ def get(self):
Will re-compute the value using `view.get(template)` if it has been
invalidated.
May raise a `NotFoundError` if the underlying view has been
invalidated.
May raise a `NotFoundError` if the underlying view is missing.
"""
if self.value is self._MISSING:
# will raise a NotFoundError if no default value was provided
self.value = templates.as_template(self.template).get_default_value()
if self.value is self._INVALID:
self.value = self.view.get(self.template)
return self.value
Expand All @@ -37,11 +32,6 @@ def _invalidate(self):
"""
self.value = self._INVALID

def _set_view_missing(self):
"""Invalidate the handle, will raise `NotFoundError` on `get()`.
"""
self.value = self._MISSING


class CachedViewMixin:
def __init__(self, *args, **kwargs):
Expand All @@ -62,9 +52,7 @@ def __getitem__(self, key) -> "CachedConfigView":
def __setitem__(self, key, value):
subview: CachedConfigView = self[key]
# invalidate the existing handles up and down the view tree
for handle in subview.handles:
handle._invalidate()
subview._invalidate_descendants(value)
subview._invalidate_descendants()
self._invalidate_ancestors()

return super().__setitem__(key, value)
Expand All @@ -82,24 +70,13 @@ def _invalidate_ancestors(self):
break
parent = parent.parent

def _invalidate_descendants(self, new_val):
"""Invalidate the handles for (sub)keys that were updated and
set_view_missing for keys that are absent in new_val.
def _invalidate_descendants(self):
"""Invalidate the handles for (sub)keys that were updated.
"""
for handle in self.handles:
handle._invalidate()
for subview in self.subviews.values():
try:
subval = new_val[subview.key]
except (KeyError, IndexError, TypeError):
# the old key doesn't exist in the new value anymore-
# set view as missing for the handles.
for handle in subview.handles:
handle._set_view_missing()
subval = None
else:
# old key is present, possibly with a new value- invalidate.
for handle in subview.handles:
handle._invalidate()
subview._invalidate_descendants(subval)
subview._invalidate_descendants()

def get_handle(self, template=templates.REQUIRED):
"""Retreive a `CachedHandle` for the current view and template.
Expand Down
11 changes: 4 additions & 7 deletions test/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import confuse
from confuse.cache import CachedConfigView, CachedHandle, CachedRootView
from confuse.exceptions import NotFoundError
from confuse.templates import Sequence


Expand Down Expand Up @@ -35,19 +34,17 @@ def test_missing(self):
handle: CachedHandle = view.get_handle(Sequence(int))

self.config['x'] = {'p': [4, 5]}
# new dict doesn't have a 'y' key
with self.assertRaises(NotFoundError):
handle.get()
# new dict doesn't have a 'y' key, but according to the view-theory,
# it will get the value from the older view that has been shadowed.
self.assertEqual(handle.get(), [1, 2])

def test_missing2(self):
view: CachedConfigView = self.config['x']['w']
handle = view.get_handle(str)
self.assertEqual(handle.get(), 'z')

self.config['x'] = {'y': [4, 5]}
# new dict doesn't have a 'w' key
with self.assertRaises(NotFoundError):
handle.get()
self.assertEqual(handle.get(), 'z')

def test_list_update(self):
view: CachedConfigView = self.config['a'][1]
Expand Down

0 comments on commit ac5485b

Please sign in to comment.