Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HJ-319 Add cache-clearing methods to DBCache #5629

Merged
merged 2 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ The types of changes are:

## [Unreleased](https://github.com/ethyca/fides/compare/2.52.0...main)

### Added
- Added cache-clearing methods to the `DBCache` model to allow deleting cache entries [#5629](https://github.com/ethyca/fides/pull/5629)



## [2.52.0](https://github.com/ethyca/fides/compare/2.51.2...2.52.0)
Expand Down
38 changes: 38 additions & 0 deletions src/fides/api/models/db_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,41 @@ def set_cache_value(
db.commit()
db.refresh(db_cache_entry)
return db_cache_entry

@classmethod
def delete_cache_entry(
cls,
db: Session,
namespace: DBCacheNamespace,
cache_key: str,
) -> None:
"""
Deletes the cache entry for the given cache_key
"""
db.query(cls).filter(
cls.namespace == namespace.value, cls.cache_key == cache_key
).delete()
db.commit()

@classmethod
def clear_cache_for_namespace(
cls,
db: Session,
namespace: DBCacheNamespace,
) -> None:
"""
Deletes all cache entries for the given namespace
"""
db.query(cls).filter(cls.namespace == namespace.value).delete()
db.commit()

@classmethod
def clear_cache(
cls,
db: Session,
) -> None:
"""
Deletes all cache entries
"""
db.query(cls).delete()
db.commit()
184 changes: 184 additions & 0 deletions tests/ops/models/test_dbcache.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
from enum import Enum

from fides.api.models.db_cache import DBCache, DBCacheNamespace


# enum used to test extra namespaces since right now DBCacheNamespace only has one value
# this can be removed once more namespaces are added
class TestDbCacheNamespace(Enum):
TEST_NAMESPACE = "test-namespace"


class TestDBCacheModel:
def test_get_nonexisting_entry(self, db):
cache_value = DBCache.get_cache_value(
Expand Down Expand Up @@ -51,3 +59,179 @@ def test_update_cache_value(self, db):
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key"
)
assert updated_value.decode() == "value 2"

def test_delete_cache_entry(self, db):
# Add two entries
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"some-key",
"value 1".encode(),
)
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"some-key-2",
"value 2".encode(),
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key"
).decode()
== "value 1"
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key-2"
).decode()
== "value 2"
)

# Delete the first entry
DBCache.delete_cache_entry(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key"
)

# Check the first entry was deleted
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key"
)
is None
)

# Check the second entry still exists
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "some-key-2"
).decode()
== "value 2"
)

def test_clear_cache_for_namespace(self, db):
# Add three entries, two belonging to namespace LIST_PRIVACY_EXPERIENCE and one to another namespace
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"key-1",
"value 1".encode(),
)
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"key-2",
"value 2".encode(),
)
DBCache.set_cache_value(
db,
TestDbCacheNamespace.TEST_NAMESPACE,
"key-1",
"value 3".encode(),
)

# Check all entries exist
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-1"
).decode()
== "value 1"
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-2"
).decode()
== "value 2"
)
assert (
DBCache.get_cache_value(
db, TestDbCacheNamespace.TEST_NAMESPACE, "key-1"
).decode()
== "value 3"
)

# Clear the cache for LIST_PRIVACY_EXPERIENCE namespace
DBCache.clear_cache_for_namespace(db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE)

# Check the entries belonging to LIST_PRIVACY_EXPERIENCE were deleted
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-1"
)
is None
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-2"
)
is None
)

# Check the entry belonging to another namespace still exists
assert (
DBCache.get_cache_value(
db, TestDbCacheNamespace.TEST_NAMESPACE, "key-1"
).decode()
== "value 3"
)

def test_clear_cache(self, db):
# Add three entries, two belonging to namespace LIST_PRIVACY_EXPERIENCE and one to another namespace
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"key-1",
"value 1".encode(),
)
DBCache.set_cache_value(
db,
DBCacheNamespace.LIST_PRIVACY_EXPERIENCE,
"key-2",
"value 2".encode(),
)
DBCache.set_cache_value(
db,
TestDbCacheNamespace.TEST_NAMESPACE,
"key-1",
"value 3".encode(),
)

# Check all entries exist
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-1"
).decode()
== "value 1"
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-2"
).decode()
== "value 2"
)
assert (
DBCache.get_cache_value(
db, TestDbCacheNamespace.TEST_NAMESPACE, "key-1"
).decode()
== "value 3"
)

# Clear the cache
DBCache.clear_cache(db)

# Check all entries were deleted
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-1"
)
is None
)
assert (
DBCache.get_cache_value(
db, DBCacheNamespace.LIST_PRIVACY_EXPERIENCE, "key-2"
)
is None
)
assert (
DBCache.get_cache_value(db, TestDbCacheNamespace.TEST_NAMESPACE, "key-1")
is None
)
Loading