Skip to content
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
66 changes: 47 additions & 19 deletions geonode/metadata/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@
import logging
import copy
from cachetools import FIFOCache
from datetime import datetime

from django.utils.translation import gettext as _

from geonode.base.models import Thesaurus, ThesaurusKeyword, ThesaurusKeywordLabel
from geonode.base.models import Thesaurus
from geonode.metadata.handlers.abstract import MetadataHandler
from geonode.metadata.exceptions import UnsetFieldException
from geonode.metadata.i18n import get_localized_labels, I18N_THESAURUS_IDENTIFIER
Expand Down Expand Up @@ -88,13 +89,23 @@

def get_schema(self, lang=None):
cache_key = str(lang)
ret = MetadataManager._schema_cache.get(cache_key, None)
if not ret:
logger.info(f"Building schema for {cache_key}")
ret = self.build_schema(lang)
MetadataManager._schema_cache[cache_key] = ret
logger.info("Schema built")
return ret
cached_entry = MetadataManager._schema_cache.get(cache_key, None)

thesaurus_date = (
Thesaurus.objects.filter(identifier=I18N_THESAURUS_IDENTIFIER).values_list("date", flat=True).first()
)
if cached_entry:
if thesaurus_date == cached_entry["date"]:
# only return cached schema if thesaurus has not been modified
return cached_entry["schema"]
else:
logger.info(f"Schema for {cache_key} needs to be recreated")

Check warning on line 102 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L102

Added line #L102 was not covered by tests

logger.info(f"Building schema for {cache_key}")
schema = self.build_schema(lang)
logger.debug("Schema built")
MetadataManager._schema_cache[cache_key] = {"schema": schema, "date": thesaurus_date}
return schema

def build_schema_instance(self, resource, lang=None):
schema = self.get_schema(lang)
Expand Down Expand Up @@ -186,18 +197,35 @@
_create_test_errors(schema["items"], errors, path, msg_template, create_message=False)


# signals for invalidating cached data
def thesaurus_changed(sender, instance, **kwargs):
base = f"Thesaurus changed: class {sender.__class__.__name__} -->"
if sender == Thesaurus and instance.identifier == I18N_THESAURUS_IDENTIFIER:
logger.debug(f"{base} {instance.identifier}")
MetadataManager.clear_schema_cache()
elif sender == ThesaurusKeyword and instance.thesaurus.identifier == I18N_THESAURUS_IDENTIFIER:
logger.debug(f"{base} {instance.about} ALT:{instance.alt_label}")
MetadataManager.clear_schema_cache()
elif sender == ThesaurusKeywordLabel and instance.keyword.thesaurus.identifier == I18N_THESAURUS_IDENTIFIER:
logger.debug(f"{base} {instance.keyword.about} ALT:{instance.keyword.alt_label} L:{instance.lang}")
MetadataManager.clear_schema_cache()
if instance.identifier == I18N_THESAURUS_IDENTIFIER:
if hasattr(instance, "_signal_handled"): # avoid signal recursion
return
logger.debug(f"Thesaurus changed: {instance.identifier}")
_update_thesaurus_date()

Check warning on line 205 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L203-L205

Added lines #L203 - L205 were not covered by tests


def thesaurusk_changed(sender, instance, **kwargs):
if instance.thesaurus.identifier == I18N_THESAURUS_IDENTIFIER:
logger.debug(f"ThesaurusKeyword changed: {instance.about} ALT:{instance.alt_label}")
_update_thesaurus_date()

Check warning on line 211 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L210-L211

Added lines #L210 - L211 were not covered by tests


def thesauruskl_changed(sender, instance, **kwargs):
if instance.keyword.thesaurus.identifier == I18N_THESAURUS_IDENTIFIER:
logger.debug(

Check warning on line 216 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L216

Added line #L216 was not covered by tests
f"ThesaurusKeywordLabel changed: {instance.keyword.about} ALT:{instance.keyword.alt_label} L:{instance.lang}"
)
_update_thesaurus_date()

Check warning on line 219 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L219

Added line #L219 was not covered by tests


def _update_thesaurus_date():
logger.debug("Updating label thesaurus date")

Check warning on line 223 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L223

Added line #L223 was not covered by tests
# update timestamp to invalidate other processes also
i18n_thesaurus = Thesaurus.objects.get(identifier=I18N_THESAURUS_IDENTIFIER)
i18n_thesaurus.date = datetime.now().replace(microsecond=0).isoformat()
i18n_thesaurus._signal_handled = True
i18n_thesaurus.save()

Check warning on line 228 in geonode/metadata/manager.py

View check run for this annotation

Codecov / codecov/patch

geonode/metadata/manager.py#L225-L228

Added lines #L225 - L228 were not covered by tests


metadata_manager = MetadataManager()
7 changes: 3 additions & 4 deletions geonode/metadata/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
from django.db.models.signals import post_save

from geonode.base.models import Thesaurus, ThesaurusKeyword, ThesaurusKeywordLabel
from geonode.metadata.manager import thesaurus_changed

from geonode.metadata.manager import thesaurus_changed, thesaurusk_changed, thesauruskl_changed

logger = logging.getLogger(__name__)


def connect_signals():
logger.debug("Setting up signal connections...")
post_save.connect(thesaurus_changed, sender=Thesaurus, weak=False, dispatch_uid="metadata_reset_t")
post_save.connect(thesaurus_changed, sender=ThesaurusKeyword, weak=False, dispatch_uid="metadata_reset_tk")
post_save.connect(thesaurus_changed, sender=ThesaurusKeywordLabel, weak=False, dispatch_uid="metadata_reset_tkl")
post_save.connect(thesaurusk_changed, sender=ThesaurusKeyword, weak=False, dispatch_uid="metadata_reset_tk")
post_save.connect(thesauruskl_changed, sender=ThesaurusKeywordLabel, weak=False, dispatch_uid="metadata_reset_tkl")
logger.debug("Signal connections set")
11 changes: 8 additions & 3 deletions geonode/metadata/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,13 +826,18 @@ def test_build_schema(self, mock_init_schema_context, mock_root_schema):
@patch("cachetools.FIFOCache.get")
# Mock FIFOCache's __setitem__ method (cache setting)
@patch("cachetools.FIFOCache.__setitem__")
def test_get_schema(self, mock_setitem, mock_get, mock_build_schema):
@patch("geonode.metadata.manager.Thesaurus.objects.filter")
def test_get_schema(self, mock_db_value, mock_setitem, mock_get, mock_build_schema):

lang = "en"
expected_schema = self.fake_schema
thesaurus_date = "some_date_value"

# Mock the Thesaurus.objects.filter().first() method to return the thesaurus_date
mock_db_value.return_value.values_list.return_value.first.return_value = thesaurus_date

# Case when the schema is already in cache
mock_get.return_value = expected_schema
mock_get.return_value = {"schema": expected_schema, "date": thesaurus_date}
result = metadata_manager.get_schema(lang)

# Assert that the schema was retrieved from the cache
Expand All @@ -852,7 +857,7 @@ def test_get_schema(self, mock_setitem, mock_get, mock_build_schema):

mock_get.assert_called_once_with(str(lang), None)
mock_build_schema.assert_called_once_with(lang)
mock_setitem.assert_called_once_with(str(lang), expected_schema)
mock_setitem.assert_called_once_with(str(lang), {"schema": expected_schema, "date": "some_date_value"})
self.assertEqual(result, expected_schema)

@patch("geonode.metadata.manager.metadata_manager.get_schema")
Expand Down
Loading