Expire exists cache when repository is created from bundle
Problem
As mentioned in #199745 (closed) while running import with XL data set in import.rake task with RequestStore enabled, I encountered an error:
"undefined method 'lines' for nil:NilClass"
Investigation
Investigation showed that in /app/models/repository.rb we are using exists? method with cache_method_asymmetrically
# /app/models/repository.rb#L533
def exists?
return false unless full_path
raw_repository.exists?
end
cache_method_asymmetrically :exists?
Note: We are clearing this cache in after_create callback once repository is created.
But during import, repo_restorer creates repository from bundle instead:
# lib/gitlab/import_export/repo_restorer.rb
def restore
return true unless File.exist?(path_to_bundle)
repository.create_from_bundle(path_to_bundle)
...
https://gitlab.com/gitlab-org/gitlab/blob/master/lib/gitlab/import_export/repo_restorer.rb#L17
Since create_from_bundle method doesn't exist inside app/models/repository.rb, method missing is triggered, which directly calls repository_service.create_from_bundle
# app/models/repository.rb#L491
def method_missing(msg, *args, &block)
...
raw_repository.__send__(msg, *args, &block) # rubocop:disable GitlabSecurity/PublicSend
end
end
This call doesn't trigger after_create callback, and doesn't clear expire_exists_cache.
Conclusion
In case when RequestStore is enabled, repository.exists? method will always return false, and actual blob for diff file will never be retrieved from the repository.
This will cause unfolding diff lines to crash.
Fix
We should clear the cache by running expire_exists_cache, once repository is created from bundle
Conformity
-
Changelog entry -
Documentation (if required) -
Code review guidelines -
Merge request performance guidelines -
Style guides -
Database guides -
Separation of EE specific content
Closes #199745 (closed)