-
-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support concurrent loading of Config for different namespaces (#29)
* Support concurrent loading of Config for different namespaces. * Supports loading the apollo module through spi
- Loading branch information
Showing
8 changed files
with
391 additions
and
156 deletions.
There are no files selected for viewing
62 changes: 62 additions & 0 deletions
62
...lo-client/src/main/java/com/ctrip/framework/apollo/internals/ConcurrentConfigManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* | ||
* Copyright 2022 Apollo Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
package com.ctrip.framework.apollo.internals; | ||
|
||
import com.ctrip.framework.apollo.Config; | ||
import com.ctrip.framework.apollo.ConfigFile; | ||
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; | ||
import com.google.common.collect.Maps; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* @author tian | ||
*/ | ||
public class ConcurrentConfigManager extends DefaultConfigManager { | ||
|
||
private final Map<String, Object> m_configLocks = Maps.newConcurrentMap(); | ||
private final Map<String, Object> m_configFileLocks = Maps.newConcurrentMap(); | ||
|
||
@Override | ||
public Config getConfig(String namespace) { | ||
String lockKey = buildLockKey(namespace); | ||
Object lock = m_configLocks.get(lockKey); | ||
if (lock == null) { | ||
synchronized (lockKey) { | ||
lock = m_configLocks.computeIfAbsent(lockKey, k -> new Object()); | ||
} | ||
} | ||
return getConfigInLock(lock, namespace); | ||
} | ||
|
||
@Override | ||
public ConfigFile getConfigFile(String namespace, ConfigFileFormat configFileFormat) { | ||
String namespaceFileName = buildNamespaceFileName(namespace, configFileFormat); | ||
String lockKey = buildLockKey(namespaceFileName); | ||
Object lock = m_configFileLocks.get(lockKey); | ||
if (lock == null) { | ||
synchronized (lockKey) { | ||
lock = m_configFileLocks.computeIfAbsent(lockKey, k -> new Object()); | ||
} | ||
} | ||
return getConfigFileInLock(lock, namespaceFileName, configFileFormat); | ||
} | ||
|
||
private String buildLockKey(String factor) { | ||
return (String.format("%s.%s", getClass().getName(), factor)).intern(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
167 changes: 167 additions & 0 deletions
167
...-client/src/test/java/com/ctrip/framework/apollo/internals/AbstractConfigManagerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
/* | ||
* Copyright 2022 Apollo Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
package com.ctrip.framework.apollo.internals; | ||
|
||
import static org.hamcrest.core.IsEqual.equalTo; | ||
import static org.junit.Assert.assertEquals; | ||
import static org.hamcrest.MatcherAssert.assertThat; | ||
import static org.mockito.Mockito.mock; | ||
|
||
import com.ctrip.framework.apollo.enums.ConfigSourceType; | ||
import java.util.Properties; | ||
import java.util.Set; | ||
|
||
import org.junit.After; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import com.ctrip.framework.apollo.Config; | ||
import com.ctrip.framework.apollo.ConfigFile; | ||
import com.ctrip.framework.apollo.build.MockInjector; | ||
import com.ctrip.framework.apollo.core.enums.ConfigFileFormat; | ||
import com.ctrip.framework.apollo.spi.ConfigFactory; | ||
import com.ctrip.framework.apollo.spi.ConfigFactoryManager; | ||
import com.ctrip.framework.apollo.util.ConfigUtil; | ||
|
||
/** | ||
* @author tian | ||
*/ | ||
public abstract class AbstractConfigManagerTest { | ||
private ConfigManager configManager; | ||
private static String someConfigContent; | ||
|
||
protected abstract ConfigManager getConfigManager(); | ||
|
||
@Before | ||
public void setUp() throws Exception { | ||
MockInjector.setInstance(ConfigFactoryManager.class, new MockConfigFactoryManager()); | ||
MockInjector.setInstance(ConfigUtil.class, new ConfigUtil()); | ||
configManager = getConfigManager(); | ||
someConfigContent = "someContent"; | ||
} | ||
|
||
@After | ||
public void tearDown() throws Exception { | ||
MockInjector.reset(); | ||
} | ||
|
||
@Test | ||
public void testGetConfig() throws Exception { | ||
String someNamespace = "someName"; | ||
String anotherNamespace = "anotherName"; | ||
String someKey = "someKey"; | ||
Config config = configManager.getConfig(someNamespace); | ||
Config anotherConfig = configManager.getConfig(anotherNamespace); | ||
|
||
assertEquals(someNamespace + ":" + someKey, config.getProperty(someKey, null)); | ||
assertEquals(anotherNamespace + ":" + someKey, anotherConfig.getProperty(someKey, null)); | ||
} | ||
|
||
@Test | ||
public void testGetConfigMultipleTimesWithSameNamespace() throws Exception { | ||
String someNamespace = "someName"; | ||
Config config = configManager.getConfig(someNamespace); | ||
Config anotherConfig = configManager.getConfig(someNamespace); | ||
|
||
assertThat( | ||
"Get config multiple times with the same namespace should return the same config instance", | ||
config, equalTo(anotherConfig)); | ||
} | ||
|
||
@Test | ||
public void testGetConfigFile() throws Exception { | ||
String someNamespace = "someName"; | ||
ConfigFileFormat someConfigFileFormat = ConfigFileFormat.Properties; | ||
|
||
ConfigFile configFile = | ||
configManager.getConfigFile(someNamespace, someConfigFileFormat); | ||
|
||
assertEquals(someConfigFileFormat, configFile.getConfigFileFormat()); | ||
assertEquals(someConfigContent, configFile.getContent()); | ||
} | ||
|
||
@Test | ||
public void testGetConfigFileMultipleTimesWithSameNamespace() throws Exception { | ||
String someNamespace = "someName"; | ||
ConfigFileFormat someConfigFileFormat = ConfigFileFormat.Properties; | ||
|
||
ConfigFile someConfigFile = | ||
configManager.getConfigFile(someNamespace, someConfigFileFormat); | ||
ConfigFile anotherConfigFile = | ||
configManager.getConfigFile(someNamespace, someConfigFileFormat); | ||
|
||
assertThat( | ||
"Get config file multiple times with the same namespace should return the same config file instance", | ||
someConfigFile, equalTo(anotherConfigFile)); | ||
|
||
} | ||
|
||
public static class MockConfigFactoryManager implements ConfigFactoryManager { | ||
|
||
@Override | ||
public ConfigFactory getFactory(String namespace) { | ||
return new ConfigFactory() { | ||
@Override | ||
public Config create(final String namespace) { | ||
return new AbstractConfig() { | ||
@Override | ||
public String getProperty(String key, String defaultValue) { | ||
return namespace + ":" + key; | ||
} | ||
|
||
@Override | ||
public Set<String> getPropertyNames() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public ConfigSourceType getSourceType() { | ||
return null; | ||
} | ||
}; | ||
} | ||
|
||
@Override | ||
public ConfigFile createConfigFile(String namespace, final ConfigFileFormat configFileFormat) { | ||
ConfigRepository someConfigRepository = mock(ConfigRepository.class); | ||
return new AbstractConfigFile(namespace, someConfigRepository) { | ||
|
||
@Override | ||
protected void update(Properties newProperties) { | ||
|
||
} | ||
|
||
@Override | ||
public String getContent() { | ||
return someConfigContent; | ||
} | ||
|
||
@Override | ||
public boolean hasContent() { | ||
return true; | ||
} | ||
|
||
@Override | ||
public ConfigFileFormat getConfigFileFormat() { | ||
return configFileFormat; | ||
} | ||
}; | ||
} | ||
}; | ||
} | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
...lient/src/test/java/com/ctrip/framework/apollo/internals/ConcurrentConfigManagerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
* Copyright 2022 Apollo Authors | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
package com.ctrip.framework.apollo.internals; | ||
|
||
/** | ||
* @author tian | ||
*/ | ||
public class ConcurrentConfigManagerTest extends AbstractConfigManagerTest { | ||
|
||
@Override | ||
protected ConfigManager getConfigManager() { | ||
return new ConcurrentConfigManager(); | ||
} | ||
} |
Oops, something went wrong.