Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support incremental configuration synchronization client #90

Merged
merged 25 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f654cb3
feat: support incremental configuration synchronization client
jackie-coming Nov 26, 2024
44b70fa
Merge remote-tracking branch 'upstream/main' into feautre/Incremental…
jackie-coming Dec 8, 2024
6859fe1
code format
jackie-coming Dec 8, 2024
9842289
add Unknown sync mode
jackie-coming Dec 14, 2024
b454698
code format
jackie-coming Dec 20, 2024
89321ac
code format
jackie-coming Dec 21, 2024
08e2705
code format
jackie-coming Dec 21, 2024
69f4677
code format
jackie-coming Dec 21, 2024
121317b
code format
jackie-coming Dec 21, 2024
d489886
更新 RemoteConfigRepository.java
jackie-coming Dec 22, 2024
4e9e146
更新 ApolloConfig.java
jackie-coming Dec 22, 2024
545c074
更新 ApolloConfig.java
jackie-coming Dec 22, 2024
07b3b13
更新 ConfigurationChange.java
jackie-coming Dec 22, 2024
be92b58
更新 ConfigSyncType.java
jackie-coming Dec 22, 2024
201b782
更新 ConfigSyncType.java
jackie-coming Dec 22, 2024
eb737cf
更新 ConfigSyncType.java
jackie-coming Dec 22, 2024
18e2139
更新 ConfigurationChange.java
jackie-coming Dec 22, 2024
81661cf
更新 ConfigurationChangeType.java
jackie-coming Dec 22, 2024
7d1ffd7
更新 ConfigurationChangeTypeUtils.java
jackie-coming Dec 22, 2024
a5a47e4
更新 ConfigSyncType.java
jackie-coming Dec 22, 2024
66aae85
code format
jackie-coming Dec 22, 2024
8cf6c6d
code format
jackie-coming Dec 22, 2024
0f7d2a3
add UnknownSync action
jackie-coming Dec 22, 2024
ee7e05a
Apply suggestions from code review
nobodyiam Dec 23, 2024
d3abb56
Merge branch 'main' into feautre/IncrementalSync
nobodyiam Dec 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Apollo Java 2.4.0
* [Add more observability in apollo config client](https://github.com/apolloconfig/apollo-java/pull/74)
* [Feature Support Kubernetes ConfigMap cache for Apollo java, golang client](https://github.com/apolloconfig/apollo-java/pull/79)
* [Feature support pulling configuration information from multiple AppIds](https://github.com/apolloconfig/apollo-java/pull/70)
* [Feature support incremental configuration synchronization client](https://github.com/apolloconfig/apollo-java/pull/90)


------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@
import com.ctrip.framework.apollo.core.ConfigConsts;
import com.ctrip.framework.apollo.core.dto.ApolloConfig;
import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;
import com.ctrip.framework.apollo.core.dto.ConfigurationChange;
import com.ctrip.framework.apollo.core.dto.ServiceDTO;
import com.ctrip.framework.apollo.core.enums.ConfigSyncType;
import com.ctrip.framework.apollo.core.enums.ConfigurationChangeType;
import com.ctrip.framework.apollo.core.schedule.ExponentialSchedulePolicy;
import com.ctrip.framework.apollo.core.schedule.SchedulePolicy;
import com.ctrip.framework.apollo.core.signature.Signature;
Expand All @@ -49,6 +52,7 @@
import com.google.common.util.concurrent.RateLimiter;
import com.google.gson.Gson;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
Expand Down Expand Up @@ -255,6 +259,24 @@ private ApolloConfig loadApolloConfig() {

ApolloConfig result = response.getBody();

if (result != null) {
ConfigSyncType configSyncType = ConfigSyncType.fromString(result.getConfigSyncType());

if (configSyncType == ConfigSyncType.INCREMENTAL_SYNC) {
nobodyiam marked this conversation as resolved.
Show resolved Hide resolved
ApolloConfig previousConfig = m_configCache.get();
Map<String, String> previousConfigurations =
(previousConfig != null) ? previousConfig.getConfigurations() : null;
result.setConfigurations(
mergeConfigurations(previousConfigurations, result.getConfigurationChanges()));
} else if (configSyncType == ConfigSyncType.UNKNOWN) {
String message = String.format(
"Apollo Config Sync type invalid - configSyncType: %s",
nobodyiam marked this conversation as resolved.
Show resolved Hide resolved
result.getConfigSyncType());
throw new ApolloConfigException(message, exception);
}

jackie-coming marked this conversation as resolved.
Show resolved Hide resolved
}

logger.debug("Loaded config for {}: {}", m_namespace, result);

return result;
Expand All @@ -269,7 +291,7 @@ private ApolloConfig loadApolloConfig() {
statusCodeException = new ApolloConfigStatusCodeException(ex.getStatusCode(),
message);
Tracer.logEvent(APOLLO_CLIENT_NAMESPACE_NOT_FOUND,m_namespace);

}
Tracer.logEvent(APOLLO_CONFIG_EXCEPTION, ExceptionUtil.getDetailMessage(statusCodeException));
transaction.setStatus(statusCodeException);
Expand Down Expand Up @@ -363,4 +385,34 @@ private List<ServiceDTO> getConfigServices() {

return services;
}

Map<String, String> mergeConfigurations(Map<String, String> previousConfigurations,
List<ConfigurationChange> configurationChanges) {
Map<String, String> newConfigurations = new HashMap<>();

if (previousConfigurations != null) {
newConfigurations = Maps.newHashMap(previousConfigurations);
}

if (configurationChanges == null) {
return newConfigurations;
}

for (ConfigurationChange change : configurationChanges) {
switch (ConfigurationChangeType.fromString(change.getConfigurationChangeType())) {
case ADDED:
case MODIFIED:
newConfigurations.put(change.getKey(), change.getNewValue());
break;
case DELETED:
newConfigurations.remove(change.getKey());
break;
default:
//do nothing
break;
}
}

return newConfigurations;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
import com.ctrip.framework.apollo.core.dto.ApolloConfig;
import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;
import com.ctrip.framework.apollo.core.dto.ApolloNotificationMessages;
import com.ctrip.framework.apollo.core.dto.ConfigurationChange;
import com.ctrip.framework.apollo.core.dto.ServiceDTO;
import com.ctrip.framework.apollo.core.enums.ConfigSyncType;
import com.ctrip.framework.apollo.core.signature.Signature;
import com.ctrip.framework.apollo.enums.ConfigSourceType;
import com.ctrip.framework.apollo.exceptions.ApolloConfigException;
Expand All @@ -53,6 +55,7 @@
import com.google.common.util.concurrent.SettableFuture;
import com.google.gson.Gson;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
Expand Down Expand Up @@ -154,6 +157,141 @@ public void testLoadConfig() throws Exception {
assertEquals(ConfigSourceType.REMOTE, remoteConfigRepository.getSourceType());
}

@Test
public void testLoadConfigWithIncrementalSync() throws Exception {

String someKey = "someKey";
String someValue = "someValue";
String someKey1 = "someKey1";
String someValue1 = "someKey1";
Map<String, String> configurations = Maps.newHashMap();
configurations.put(someKey, someValue);
configurations.put(someKey1, someValue1);
ApolloConfig someApolloConfig = assembleApolloConfig(configurations);

when(someResponse.getStatusCode()).thenReturn(200);
when(someResponse.getBody()).thenReturn(someApolloConfig);

RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someAppId,
someNamespace);

remoteConfigRepository.sync();

List<ConfigurationChange> configurationChanges = new ArrayList<>();
String someNewValue = "someNewValue";
configurationChanges.add(new ConfigurationChange(someKey, someNewValue, "MODIFIED"));
configurationChanges.add(new ConfigurationChange(someKey1, null, "DELETED"));
String someKey2 = "someKey2";
String someValue2 = "someValue2";
configurationChanges.add(new ConfigurationChange(someKey2, someValue2, "ADDED"));
ApolloConfig someApolloConfigWithIncrementalSync = assembleApolloConfigWithIncrementalSync(
configurationChanges);

when(someResponse.getStatusCode()).thenReturn(200);
when(someResponse.getBody()).thenReturn(someApolloConfigWithIncrementalSync);

remoteConfigRepository.sync();

Properties config = remoteConfigRepository.getConfig();

assertEquals(2, config.size());
assertEquals("someNewValue", config.getProperty("someKey"));
assertEquals("someValue2", config.getProperty("someKey2"));
assertEquals(ConfigSourceType.REMOTE, remoteConfigRepository.getSourceType());
remoteConfigLongPollService.stopLongPollingRefresh();
}

@Test
public void testMergeConfigurations() throws Exception {
String key1 = "key1";
String value1 = "value1";
String anotherValue1 = "anotherValue1";

String key3 = "key3";
String value3 = "value3";
Map<String, String> previousConfigurations = ImmutableMap.of(key1, value1, key3, value3);

List<ConfigurationChange> configurationChanges = new ArrayList<>();
configurationChanges.add(new ConfigurationChange(key1, anotherValue1, "MODIFIED"));
String key2 = "key2";
String value2 = "value2";
configurationChanges.add(new ConfigurationChange(key2, value2, "ADDED"));
configurationChanges.add(new ConfigurationChange(key3, null, "DELETED"));

RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someAppId,
someNamespace);
Map<String, String> result = remoteConfigRepository.mergeConfigurations(previousConfigurations,
configurationChanges);

assertEquals(2, result.size());
assertEquals(anotherValue1, result.get(key1));
assertEquals(value2, result.get(key2));
}

@Test
public void testMergeConfigurationWithPreviousConfigurationsIsNULL() throws Exception {
String key1 = "key1";
String value1 = "value1";

String key3 = "key3";
String value3 = "value3";

Map<String, String> previousConfigurations = ImmutableMap.of(key1, value1, key3, value3);

RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someAppId,
someNamespace);
Map<String, String> result = remoteConfigRepository.mergeConfigurations(previousConfigurations,
null);

assertEquals(2, result.size());
assertEquals(value1, result.get(key1));
assertEquals(value3, result.get(key3));
}

@Test
public void testMergeConfigurationWithChangesIsNULL() throws Exception {
String key1 = "key1";
String value1 = "value1";
String anotherValue1 = "anotherValue1";

String key3 = "key3";
String value3 = "value3";

List<ConfigurationChange> configurationChanges = new ArrayList<>();
configurationChanges.add(new ConfigurationChange(key1, anotherValue1, "MODIFIED"));
String key2 = "key2";
String value2 = "value2";
configurationChanges.add(new ConfigurationChange(key2, value2, "ADDED"));
configurationChanges.add(new ConfigurationChange(key3, null, "DELETED"));

RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someAppId,
someNamespace);
Map<String, String> result = remoteConfigRepository.mergeConfigurations(null,
configurationChanges);

assertEquals(2, result.size());
assertEquals(anotherValue1, result.get(key1));
assertEquals(value2, result.get(key2));
}

@Test(expected = ApolloConfigException.class)
public void testGetRemoteConfigWithUnknownSync() throws Exception {

ApolloConfig someApolloConfigWithUnknownSync = assembleApolloConfigWithUnknownSync(
new ArrayList<>());

when(someResponse.getStatusCode()).thenReturn(200);
when(someResponse.getBody()).thenReturn(someApolloConfigWithUnknownSync);

RemoteConfigRepository remoteConfigRepository = new RemoteConfigRepository(someAppId,
someNamespace);

//must stop the long polling before exception occurred
remoteConfigLongPollService.stopLongPollingRefresh();

remoteConfigRepository.getConfig();
}

@Test
public void testLoadConfigWithOrderedProperties() throws Exception {
String someKey = "someKey";
Expand Down Expand Up @@ -371,6 +509,32 @@ private ApolloConfig assembleApolloConfig(Map<String, String> configurations) {
return apolloConfig;
}

private ApolloConfig assembleApolloConfigWithIncrementalSync(
List<ConfigurationChange> configurationChanges) {
String someAppId = "appId";
String someClusterName = "cluster";
String someReleaseKey = "1";
ApolloConfig apolloConfig =
new ApolloConfig(someAppId, someClusterName, someNamespace, someReleaseKey);

apolloConfig.setConfigSyncType(ConfigSyncType.INCREMENTAL_SYNC.getValue());
apolloConfig.setConfigurationChanges(configurationChanges);
return apolloConfig;
}

private ApolloConfig assembleApolloConfigWithUnknownSync(
List<ConfigurationChange> configurationChanges) {
String someAppId = "appId";
String someClusterName = "cluster";
String someReleaseKey = "1";
ApolloConfig apolloConfig =
new ApolloConfig(someAppId, someClusterName, someNamespace, someReleaseKey);

apolloConfig.setConfigSyncType(ConfigSyncType.UNKNOWN.getValue());
apolloConfig.setConfigurationChanges(configurationChanges);
return apolloConfig;
}

public static class MockConfigUtil extends ConfigUtil {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
*/
package com.ctrip.framework.apollo.core.dto;


nobodyiam marked this conversation as resolved.
Show resolved Hide resolved
import java.util.List;
import java.util.Map;

/**
Expand All @@ -33,6 +35,10 @@ public class ApolloConfig {

private String releaseKey;

private String configSyncType;

private List<ConfigurationChange> configurationChanges;
nobodyiam marked this conversation as resolved.
Show resolved Hide resolved

public ApolloConfig() {
}

Expand Down Expand Up @@ -62,6 +68,14 @@ public String getReleaseKey() {
return releaseKey;
}

public String getConfigSyncType() {
return configSyncType;
}

public List<ConfigurationChange> getConfigurationChanges() {
return configurationChanges;
}

public Map<String, String> getConfigurations() {
return configurations;
}
Expand All @@ -82,10 +96,18 @@ public void setReleaseKey(String releaseKey) {
this.releaseKey = releaseKey;
}

public void setConfigSyncType(String configSyncType) {
this.configSyncType = configSyncType;
}

public void setConfigurations(Map<String, String> configurations) {
this.configurations = configurations;
}

public void setConfigurationChanges(List<ConfigurationChange> configurationChanges) {
this.configurationChanges = configurationChanges;
}

@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ApolloConfig{");
Expand Down
Loading
Loading