Cached commit counts for tags are not correctly invalidated.
Summary
Requesting commits (using commits API) for a tag before it has been pushed caches negative result. After the tag has been pushed, subsequent requests incorrectly continue to return an empty array of commits.
N.B. this does not happen for branches - after the new branch is pushed, the API correctly returns commits on the branch.
Steps to reproduce
-
Request commits for a non-existent tag
curl -fs \ -H"PRIVATE-TOKEN: $TOKEN" \ "https://git.treatwell.net/api/v4/projects/8/repository/commits?ref_name=$TAG"
JSON response (as expected) is:
[]
-
Push that tag
git tag -m "new tag" -a $TAG git push --tags
-
Re-request commits:
curl -fs \ -H"PRIVATE-TOKEN: $TOKEN" \ "https://git.treatwell.net/api/v4/projects/8/repository/commits?ref_name=$TAG"
JSON response is still an empty array:
[]
Example Project
Any gitlab project.
What is the current bug behavior?
In step 3, no commits are returned.
What is the expected correct behavior?
In step 3, commits should be returned.
If I delete the commit_count object for this tag from Redis then I get the correct response from the API:
redis /var/opt/gitlab/redis/redis.socket> GET cache:gitlab:commit_count_<TAG>:<PROJECT_PATH>:<PROJECT_ID>
"\x04\bo: ActiveSupport::Cache::Entry\t:\x0b@valuei\x00:\r@version0:\x10@created_atf\x171604054529.6717532:\x10@expires_inf\r1.2096e6"
redis /var/opt/gitlab/redis/redis.socket> DEL cache:gitlab:commit_count_<TAG>:<PROJECT_PATH>:<PROJECT_ID>
(integer) 1
Relevant logs and/or screenshots
N/A
Output of checks
N/A
Results of GitLab environment info
Gitlab 13.3.7 EE (Omnibus Docker image)
Possible fixes
You can see that commit counts are invalidated on branch push here:
https://gitlab.com/gitlab-org/gitlab/-/blob/v13.3.7-ee/app/models/repository.rb#L359
There is an interesting comment here suggested that expire_tags_cache
or expire_caches_for_tags
should be called:
https://gitlab.com/gitlab-org/gitlab/-/blob/v13.3.7-ee/app/models/repository.rb#L441
but those methods do not operate on the commit_count cache, so a call to
cache.expire(:"commit_count_#{push_tag}")
around https://gitlab.com/gitlab-org/gitlab/-/blob/v13.3.7-ee/app/models/repository.rb#L443 might do the trick.