Skip to content

Commit 4279fa4

Browse files
committed
Invalidate the content cache once a new repository version is complete
Repository.new_version() cleared the cache of the distributions serving the repository when the new version was started. Until that version is complete, those distributions are still served from the previous one, so a response computed in that window was put back into the cache and served until it expired (ten minutes by default), although the new version had been created in the meantime. Clear the cache once the new version is complete and committed instead. A version that changes nothing is discarded and no longer clears the cache. Closes: #8246
1 parent 0f6df7d commit 4279fa4

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

‎CHANGES/8246.bugfix‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed responses for a distribution being cached from the previous repository version, and served until the cache entry expired, when they were requested while a new version was being created.

‎pulpcore/app/models/repository.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,6 @@ def new_version(self, base_version=None):
198198
resource = CreatedResource(content_object=version)
199199
resource.save()
200200

201-
self.invalidate_cache()
202-
203201
return version
204202

205203
def initialize_new_version(self, new_version):
@@ -1534,6 +1532,7 @@ def __exit__(self, exc_type, exc_value, traceback):
15341532
self.repository.save()
15351533
self.save()
15361534
self._compute_counts()
1535+
transaction.on_commit(self.repository.invalidate_cache)
15371536
self.repository.cleanup_old_versions()
15381537
repository.on_new_version(self)
15391538
except Exception:

pulpcore/tests/unit/models/test_publication_retention.py renamed to pulpcore/tests/unit/models/test_caching_and_retention.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -614,3 +614,44 @@ def test_ignores_repository_distribution_when_deleted_not_latest_for_repository(
614614
assert cache_key(dist_repo.base_path) not in invalidated, (
615615
"repo dist should NOT be invalidated (pub2 still latest)"
616616
)
617+
618+
619+
@pytest.mark.django_db
620+
class TestCacheInvalidationOnRepositoryVersionCreate:
621+
"""
622+
While a new repository version is being created, the repository's distributions are still
623+
served from the previous one, and a response computed then can be put into the cache.
624+
Clearing the cache only when the version is started would leave that response there until
625+
it expires, so the cache must be cleared once the new version is complete.
626+
"""
627+
628+
def test_invalidates_once_new_version_is_complete(
629+
self, settings, django_capture_on_commit_callbacks
630+
):
631+
"""Creating a repository version invalidates the cache after the version is complete."""
632+
settings.CACHE_ENABLED = True
633+
repo = FileRepository.objects.create(name=f"repo-{uuid.uuid4().hex[:8]}")
634+
dist = dist_factory(repo=repo)
635+
complete_at_invalidation = []
636+
637+
def record(*args, base_key=None, **kwargs):
638+
if base_key is not None and cache_key(dist.base_path) in base_key:
639+
complete_at_invalidation.append(repo.versions.latest("number").complete)
640+
641+
with mock.patch("pulpcore.app.models.repository.Cache") as mock_cache:
642+
mock_cache.return_value.delete.side_effect = record
643+
with django_capture_on_commit_callbacks(execute=True):
644+
version = create_version(repo, add=["some-file.txt"])
645+
assert version.complete
646+
assert True in complete_at_invalidation
647+
648+
def test_ignores_version_without_changes(self, settings, django_capture_on_commit_callbacks):
649+
"""A new version that changes nothing is discarded and leaves the cache alone."""
650+
settings.CACHE_ENABLED = True
651+
repo = FileRepository.objects.create(name=f"repo-{uuid.uuid4().hex[:8]}")
652+
dist_factory(repo=repo)
653+
with mock.patch("pulpcore.app.models.repository.Cache") as mock_cache:
654+
with django_capture_on_commit_callbacks(execute=True):
655+
with repo.new_version():
656+
pass
657+
mock_cache.return_value.delete.assert_not_called()

0 commit comments

Comments
 (0)