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)