feat(cache): cache repository self size
Related to #823 (closed)
🌱 (Why)
Summary Calculating a repository size is currently done by evaluating an sql query on the metadata database, there is an opportunity to reduce the calculation overhead by caching the result of the calculation in the registry's redis cache and retrieving it from there in subsequent calls to the service. With this MR we aim to do exactly that. For deeper context please refer to #823 (closed).
🌱
Summary (What's in this MR) To resolve the issue #823 (closed) , this MR now does the following:
- Extends the prior repository Model to include a size attribute
- On API requests that conduct calculations of a repository's size (successfully) we update/create the repositories cached object in redis
- Invalidates (by annulling) the size attribute of a cached repository object whenever the following operations happen:
-
☣ Allows any API handlers that use the dispatcher function to utilize the existing redis cache rather than the single repo cache (when the redis cache is available)☣
🔦
Testing - Changed:
- 2 new repository integration tests and 2 new tags integration tests to validate the functionality of the cache with the store when invalidating or seting the size attribute
- Update to unit test to validate the Invalidation logic
- Unchanged (but worth noting):
🎮
Demo
🎥
https://drive.google.com/file/d/1Oc7bXjEqinpyFa7R2GISR9ii039SYlLT/view?usp=share_link
Setup
- Run the container-registry with a metadata-database and a redis cache instance
- Setup a monitor for changes to the redis cache to see which keys are being modified in redis.
For example; you can do this with
redis-cli
like so :redis-cli -a 'asecret' psubscribe '__key*__:*'
- Push an image to the registry
- Monitor the redis cache (as instructed in 2.) to see what key was modified
- Retrieve the value of the key (e.g via
redis-cli GET {{key}}
) and observe the that the value is the repository object with it's size field set to nil/null - Make a request to the registry for the size of the repo that was just pushed (e.g
curl registry:5000/gitlab/v1/repositories/{repoPath}/?size=self
) and monitor (as instructed in 2.) redis to get the key that was modified - Lookup (again) the modified key (e.g via
redis-cli GET {{key}}
), the value should be the same value obtained in 5 but with the size field filled in (i.e not nil) - Make another request to
registry:5000/gitlab/v1/repositories/docker/?size=self
notice that the cached object was not updated this time around (you can verify this by checking the TTL of the cached object and comparing it to its previous ttl) (e.g viaredis-cli TTL {{key}}
) - Make a request to the registry to untag the image that was just pushed (e.g
curl -X DELETE registry:5000/v2/<name>/tags/reference/<tag>
). - Check that the size attribute of the cached key is set to nil (as instructed in 5.);
- Query for the size of the repository again (as instructed in 6.), and verify the returned value has a changed size than what was obtained from 7.
Edited by Suleimi Ahmed