Bug updating snippet without repository
At the moment, there is a bug, when the snippet doesn't have a repository and the feature flag is on. In the successful scenario, when we update the snippet, a new repository will be created and the info will be committed. Nevertheless, an error is raised.
When we update a snippet we perform all the operations inside a db transaction:
snippet.with_transaction_returning_status do
snippet.save.tap do |saved|
break false unless saved
# In order to avoid non migrated snippets scenarios,
# if the snippet does not have a repository we created it
# We don't need to check if the repository exists
# because `create_repository` already handles it
if Feature.enabled?(:version_snippets, current_user)
create_repository_for(snippet)
end
# If the snippet repository exists we commit always
# the changes
create_commit(snippet) if snippet.repository_exists?
end
rescue => e
Nevertheless, when we have several shards there is a race condition. When the snippet does not have a repository, we create a snippet_repository
and create the repository on disk. All this, inside a db transaction (this fact is important).
When we commit the operation, we end up in the internal API (in a different thread). This means that, when we query for snippet.repository_storage
inside the internal API, because snippet_repository
is not present (because it's only present inside the db transaction in a different thread), we pick a random storage and perform the operation on it. Obviously, this failed.
We have to perform the creation of the different objects outside the db transaction. That way will have the info in every thread.
Besides this, there is another problem. If there was an error, we roll back the snippet_repository
creation but the repo created in disk wasn't removed.
An there is one more problem. We have to roll back the changes in !28516 (merged). There are some errors like the GRPC::Not Found
error that reveals the repository path. Instead, we will show again the generic message.