You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The ResourceController#retrieve only starts reading from disk once it has received the Resource from the repository.
At the same time another request may come in, but to fetch an Environment. Since these are different synchronized blocks (resources vs environment) the request proceeds to the same JGitEnvironmentRepository#getLocations.
So, in effect what can happen is that while fetching a resource, an environment request can modify the local repo (different label, or new commits have been fetched) before the resource file has been read.
I have got this issue on version 4.1.4
Steps to (consistently) reproduce:
Add a thread sleep before the resource is actually read in resource controller.
Create a remote repository with two branches (let's say work and master)
Add an application.properties file in work with from=work
Add an application.properties file in master with from=master
Make two Requests in parallel:
var resourceFromWorkWithConcurrency = new AtomicReference<String>();
var propsFromMaster = new AtomicReference<Properties>();
String resourceFromWorkNoConcurrency = fetchResource("work", "application.properties");
var workThread = new Thread(() -> resourceFromWorkWithConcurrency.set(fetchResource("work", "application.properties")));
var masterThread = new Thread(() -> propsFromMaster.set(fetchEnv("master")));
workThread.start();
masterThread.start();
masterThread.join();
workThread.join();
assertThat(resourceFromWorkNoConcurrency).isEqualTo("from=work\n"); // expected value
assertThat(resourceFromWorkWithConcurrency.get()).isEqualTo("from=master\n"); // bad value
assertThat(propsFromMaster.get().get("from")).isEqualTo("master");
The text was updated successfully, but these errors were encountered:
Context
Most of the logic of
ResourceController
is contained in a synchronizedretrieve
method.spring-cloud-config/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/resource/ResourceController.java
Lines 143 to 151 in d6aad0f
This method, in turn calls
ResourceRepository#findOne
and then aSearchPathLocator
is used to find locations for the resources:spring-cloud-config/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/resource/GenericResourceRepository.java
Line 67 in d6aad0f
In our context the
SearchPathLocator
is the jgit one, which modifies the content of the local git repo:spring-cloud-config/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java
Lines 257 to 263 in d6aad0f
Problem
The
ResourceController#retrieve
only starts reading from disk once it has received theResource
from the repository.At the same time another request may come in, but to fetch an
Environment
. Since these are different synchronized blocks (resources vs environment) the request proceeds to the sameJGitEnvironmentRepository#getLocations
.So, in effect what can happen is that while fetching a resource, an environment request can modify the local repo (different label, or new commits have been fetched) before the resource file has been read.
I have got this issue on version 4.1.4
Steps to (consistently) reproduce:
work
andmaster
)application.properties
file inwork
withfrom=work
application.properties
file inmaster
withfrom=master
The text was updated successfully, but these errors were encountered: