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 9 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
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,19 @@ 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()));
}

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 +286,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 +380,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,123 @@ 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
public void testLoadConfigWithOrderedProperties() throws Exception {
String someKey = "someKey";
Expand Down Expand Up @@ -371,6 +491,19 @@ 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;
}

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,20 @@ public void setReleaseKey(String releaseKey) {
this.releaseKey = releaseKey;
}

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


jackie-coming marked this conversation as resolved.
Show resolved Hide resolved
public void setConfigurations(Map<String, String> configurations) {
this.configurations = configurations;
}

public void setConfigurationChanges(List<ConfigurationChange> configurationChanges) {
this.configurationChanges = configurationChanges;
}
nobodyiam marked this conversation as resolved.
Show resolved Hide resolved


jackie-coming marked this conversation as resolved.
Show resolved Hide resolved
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ApolloConfig{");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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.core.dto;


/**
* Holds the information for a Configuration change.
*
* @author jason
jackie-coming marked this conversation as resolved.
Show resolved Hide resolved
*/
public class ConfigurationChange {

private final String key;
private final String newValue;
private final String configurationChangeType;

/**
* Constructor.
*
* @param key the key whose value is changed
* @param newValue the value after change
* @param configurationChangeType the change type
*/
public ConfigurationChange(String key, String newValue, String configurationChangeType) {
this.key = key;
this.newValue = newValue;
this.configurationChangeType = configurationChangeType;
}

public String getKey() {
return key;
}

public String getNewValue() {
return newValue;
}

public String getConfigurationChangeType() {
return configurationChangeType;
}


jackie-coming marked this conversation as resolved.
Show resolved Hide resolved
@Override
public String toString() {
final StringBuilder sb = new StringBuilder("ConfigChange{");
sb.append(" key='").append(key).append('\'');
sb.append(", newValue='").append(newValue).append('\'');
sb.append(", configurationChangeType=").append(configurationChangeType);
sb.append('}');
return sb.toString();
}
}
Loading
Loading