diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java index 1fd7ed7e..64d792e3 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepository.java @@ -92,6 +92,16 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository */ private int timeout = 5; + /** + * Time (in seconds) between refresh of the git repository + */ + private int refreshRate = 0; + + /** + * Time of the last refresh of the git repository + */ + private long lastRefresh; + /** * Flag to indicate that the repository should be cloned on startup (not on demand). * Generally leads to slower startup but faster first query. @@ -144,6 +154,15 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository this.timeout = timeout; } + public int getRefreshRate() { + return refreshRate; + } + + public void setRefreshRate(int refreshRate) { + this.refreshRate = refreshRate; + } + + public TransportConfigCallback getTransportConfigCallback() { return transportConfigCallback; } @@ -347,6 +366,11 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository protected boolean shouldPull(Git git) throws GitAPIException { boolean shouldPull; + + if (this.refreshRate > 0 && System.currentTimeMillis() - this.lastRefresh < (this.refreshRate * 1000)) { + return false; + } + Status gitStatus = git.status().call(); boolean isWorkingTreeClean = gitStatus.isClean(); String originUrl = git.getRepository().getConfig().getString("remote", "origin", @@ -392,6 +416,9 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository fetch.setRemote("origin"); fetch.setTagOpt(TagOpt.FETCH_TAGS); fetch.setRemoveDeletedRefs(deleteUntrackedBranches); + if (this.refreshRate > 0) { + this.setLastRefresh(System.currentTimeMillis()); + } configureCommand(fetch); try { @@ -617,6 +644,14 @@ public class JGitEnvironmentRepository extends AbstractScmEnvironmentRepository } } + public void setLastRefresh(long lastRefresh) { + this.lastRefresh = lastRefresh; + } + + public long getLastRefresh() { + return lastRefresh; + } + /** * Wraps the static method calls to {@link org.eclipse.jgit.api.Git} and * {@link org.eclipse.jgit.api.CloneCommand} allowing for easier unit testing. diff --git a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java index 16d9deec..1fa8cbb8 100644 --- a/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java +++ b/spring-cloud-config-server/src/main/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepository.java @@ -81,6 +81,9 @@ public class MultipleJGitEnvironmentRepository extends JGitEnvironmentRepository if (getTimeout() != 0 && repo.getTimeout() == 0) { repo.setTimeout(getTimeout()); } + if (getRefreshRate() != 0 && repo.getRefreshRate() == 0) { + repo.setRefreshRate(getRefreshRate()); + } String user = repo.getUsername(); String pass = repo.getPassword(); String passphrase = repo.getPassphrase(); diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java index 23c555aa..bc9490d8 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/JGitEnvironmentRepositoryTests.java @@ -325,6 +325,67 @@ public class JGitEnvironmentRepositoryTests { assertThat("shouldPull was false", shouldPull, is(true)); } + @Test + public void shouldNotRefresh() throws Exception { + Git git = mock(Git.class); + StatusCommand statusCommand = mock(StatusCommand.class); + Status status = mock(Status.class); + Repository repository = mock(Repository.class); + StoredConfig storedConfig = mock(StoredConfig.class); + + when(git.status()).thenReturn(statusCommand); + when(git.getRepository()).thenReturn(repository); + when(repository.getConfig()).thenReturn(storedConfig); + when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git"); + when(statusCommand.call()).thenReturn(status); + when(status.isClean()).thenReturn(true); + + JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment); + + repo.setLastRefresh(System.currentTimeMillis() - 5000); + repo.setRefreshRate(2); + + boolean shouldPull = repo.shouldPull(git); + + assertThat("shouldPull was false", shouldPull, is(true)); + + repo.setRefreshRate(30); + + shouldPull = repo.shouldPull(git); + + assertThat("shouldPull was true", shouldPull, is(false)); + } + + @Test + public void shouldUpdateLastRefresh() throws Exception { + Git git = mock(Git.class); + StatusCommand statusCommand = mock(StatusCommand.class); + Status status = mock(Status.class); + Repository repository = mock(Repository.class); + StoredConfig storedConfig = mock(StoredConfig.class); + FetchCommand fetchCommand = mock(FetchCommand.class); + FetchResult fetchResult = mock(FetchResult.class); + + when(git.status()).thenReturn(statusCommand); + when(git.getRepository()).thenReturn(repository); + when(fetchCommand.call()).thenReturn(fetchResult); + when(git.fetch()).thenReturn(fetchCommand); + when(repository.getConfig()).thenReturn(storedConfig); + when(storedConfig.getString("remote", "origin", "url")).thenReturn("http://example/git"); + when(statusCommand.call()).thenReturn(status); + when(status.isClean()).thenReturn(true); + + JGitEnvironmentRepository repo = new JGitEnvironmentRepository(this.environment); + + repo.setRefreshRate(1000); + repo.setLastRefresh(0); + repo.fetch(git, "master"); + + long timeDiff = System.currentTimeMillis() - repo.getLastRefresh(); + + assertThat("time difference ("+timeDiff+") was longer than 1 second", timeDiff < 1000L, is(true)); + } + @Test public void testFetchException() throws Exception { diff --git a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryIntegrationTests.java b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryIntegrationTests.java index e52df446..b3b08673 100644 --- a/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryIntegrationTests.java +++ b/spring-cloud-config-server/src/test/java/org/springframework/cloud/config/server/environment/MultipleJGitEnvironmentRepositoryIntegrationTests.java @@ -102,6 +102,26 @@ public class MultipleJGitEnvironmentRepositoryIntegrationTests { assertEquals(2, environment.getPropertySources().size()); } + @Test + public void mappingRepoWithRefreshRate() throws IOException { + String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo"); + String test1RepoUri = ConfigServerTestUtils.prepareLocalRepo("test1-config-repo"); + + Map repoMapping = new LinkedHashMap(); + repoMapping.put("spring.cloud.config.server.git.repos[test1].pattern", "*test1*"); + repoMapping.put("spring.cloud.config.server.git.repos[test1].uri", test1RepoUri); + repoMapping.put("spring.cloud.config.server.git.refreshRate", "30"); + this.context = new SpringApplicationBuilder(TestConfiguration.class).web(false) + .properties("spring.cloud.config.server.git.uri:" + defaultRepoUri) + .properties(repoMapping).run(); + EnvironmentRepository repository = this.context + .getBean(EnvironmentRepository.class); + repository.findOne("test1-svc", "staging", "master"); + Environment environment = repository.findOne("test1-svc", "staging", "master"); + assertEquals(2, environment.getPropertySources().size()); + assertEquals(((MultipleJGitEnvironmentRepository) repository).getRepos().get("test1").getRefreshRate(), 30); + } + @Test public void mappingRepoWithProfile() throws IOException { String defaultRepoUri = ConfigServerTestUtils.prepareLocalRepo("config-repo");