refactor:optimize metadata context operation.

Signed-off-by: Haotian Zhang <928016560@qq.com>
pull/1773/head
Haotian Zhang 2 weeks ago
parent 4d2ad436ad
commit 7af0d8db0e

@ -10,3 +10,4 @@
- [deps:upgrade to spring boot 3.4.12.](https://github.com/Tencent/spring-cloud-tencent/pull/1756)
- [fix: send unit header in tsf gw.](https://github.com/Tencent/spring-cloud-tencent/pull/1758)
- [feat: add new key for java agent nacos discovery.](https://github.com/Tencent/spring-cloud-tencent/pull/1766)
- [refactor:optimize metadata context operation.](https://github.com/Tencent/spring-cloud-tencent/pull/1773)

@ -132,7 +132,7 @@ public class DecodeTransferMetadataReactiveFilter implements WebFilter, Ordered
}
if (StringUtils.isNotBlank(targetNamespace)) {
MetadataContextHolder.get().putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataContextHolder.get().putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, targetNamespace);
}
TransHeadersTransfer.transfer(serverHttpRequest);

@ -76,7 +76,7 @@ public class EncodeTransferMedataFeignEnhancedPlugin implements EnhancedPlugin {
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> customMetadata = metadataContext.getTransitiveMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();

@ -73,7 +73,7 @@ public class EncodeTransferMedataRestTemplateEnhancedPlugin implements EnhancedP
// get metadata of current thread
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> customMetadata = metadataContext.getTransitiveMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();

@ -82,7 +82,7 @@ public class EncodeTransferMedataScgEnhancedPlugin implements EnhancedPlugin {
contextToHeaderInterceptorList.forEach(ContextToHeaderInterceptor::beforeContextToHeader);
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> customMetadata = metadataContext.getTransitiveMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();

@ -72,7 +72,7 @@ public class EncodeTransferMedataWebClientEnhancedPlugin implements EnhancedPlug
ClientRequest clientRequest = (ClientRequest) context.getOriginRequest();
MetadataContext metadataContext = MetadataContextHolder.get();
Map<String, String> customMetadata = metadataContext.getCustomMetadata();
Map<String, String> customMetadata = metadataContext.getTransitiveMetadata();
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
Map<String, String> applicationMetadata = metadataContext.getApplicationMetadata();
Map<String, String> transHeaders = metadataContext.getTransHeadersKV();

@ -52,7 +52,7 @@ public class PolarisDiscoveryHandler {
* @return list of healthy instances
*/
public InstancesResponse getHealthyInstances(String service) {
String namespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
String namespace = MetadataContextHolder.get().getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, polarisDiscoveryProperties.getNamespace());
GetHealthyInstancesRequest getHealthyInstancesRequest = new GetHealthyInstancesRequest();

@ -74,7 +74,7 @@ public final class RouterUtils {
serviceMetadata = instanceList.get(0).getServiceMetadata();
}
String namespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
String namespace = MetadataContextHolder.get().getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
ServiceKey serviceKey = new ServiceKey(namespace, serviceName);

@ -74,7 +74,7 @@ public class RouterUtilsTest {
.thenReturn(testNamespaceAndService);
MetadataContext metadataContext = Mockito.mock(MetadataContext.class);
mockedMetadataContextHolder.when(MetadataContextHolder::get).thenReturn(metadataContext);
Mockito.when(metadataContext.getContext(anyString(), anyString(), anyString()))
Mockito.when(metadataContext.getContextWithDefault(anyString(), anyString(), anyString()))
.thenReturn(testNamespaceAndService);
Mockito.when(metadataContext.getContext(anyString(), anyString()))
.thenReturn(testNamespaceAndService);

@ -21,10 +21,10 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.BiConsumer;
import com.tencent.cloud.common.constant.MetadataConstant;
import com.tencent.cloud.common.util.ApplicationContextAwareUtils;
import com.tencent.polaris.api.utils.StringUtils;
import com.tencent.polaris.metadata.core.MetadataContainer;
import com.tencent.polaris.metadata.core.MetadataMapValue;
import com.tencent.polaris.metadata.core.MetadataObjectValue;
@ -35,8 +35,11 @@ import com.tencent.polaris.metadata.core.TransitiveType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
/**
* MetadataContext to be stored in the thread.
*
* @author Haotian Zhang
*/
public class MetadataContext extends com.tencent.polaris.metadata.core.manager.MetadataContext {
/**
@ -49,6 +52,11 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
*/
public static final String FRAGMENT_DISPOSABLE = "disposable";
/**
* none context.
*/
public static final String FRAGMENT_NONE = "none";
/**
* upstream disposable Context.
*/
@ -97,12 +105,12 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
static {
String namespace = ApplicationContextAwareUtils
.getProperties("spring.cloud.polaris.namespace");
if (!StringUtils.hasText(namespace)) {
if (StringUtils.isBlank(namespace)) {
namespace = ApplicationContextAwareUtils
.getProperties("spring.cloud.polaris.discovery.namespace", "default");
}
if (!StringUtils.hasText(namespace)) {
if (StringUtils.isBlank(namespace)) {
LOG.error("namespace should not be blank. please configure spring.cloud.polaris.namespace or "
+ "spring.cloud.polaris.discovery.namespace");
}
@ -110,12 +118,12 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
String serviceName = ApplicationContextAwareUtils
.getProperties("spring.cloud.polaris.service");
if (!StringUtils.hasText(serviceName)) {
if (StringUtils.isBlank(serviceName)) {
serviceName = ApplicationContextAwareUtils.getProperties(
"spring.cloud.polaris.discovery.service", ApplicationContextAwareUtils
.getProperties("spring.application.name", null));
}
if (!StringUtils.hasText(serviceName)) {
if (StringUtils.isBlank(serviceName)) {
LOG.warn("service name should not be blank. please configure spring.cloud.polaris.service or "
+ "spring.cloud.polaris.discovery.service or spring.application.name");
}
@ -134,58 +142,85 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
LOCAL_NAMESPACE = namespace;
}
private Map<String, String> getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
Map<String, String> values = new HashMap<>();
metadataContainer.iterateMetadataValues(new BiConsumer<String, MetadataValue>() {
@Override
public void accept(String s, MetadataValue metadataValue) {
if (metadataValue instanceof MetadataStringValue) {
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue;
if (metadataStringValue.getTransitiveType() == transitiveType) {
values.put(s, metadataStringValue.getStringValue());
}
}
}
});
return values;
/**
* Get context with default value with fragment DISPOSABLE.
*
* @param key key
* @param defaultValue default value
* @return value
*/
public String getContextWithDefault(String key, String defaultValue) {
String value = getContext(key);
return StringUtils.isBlank(value) ? defaultValue : value;
}
public void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller, Map<String, String> values) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
for (Map.Entry<String, String> entry : values.entrySet()) {
metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), transitiveType);
/**
* Get context with fragment DISPOSABLE.
*
* @param key key
* @return value
*/
public String getContext(String key) {
Map<String, String> fragmentContext = getFragmentContext(FRAGMENT_DISPOSABLE);
if (fragmentContext == null) {
return null;
}
return fragmentContext.get(key);
}
private Map<String, String> getMapMetadataAsMap(MetadataType metadataType, String mapKey, TransitiveType transitiveType, boolean caller) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
Map<String, String> values = new HashMap<>();
MetadataValue metadataValue = metadataContainer.getMetadataValue(mapKey);
if (!(metadataValue instanceof MetadataMapValue)) {
return values;
/**
* Get context with default value with fragment.
*
* @param fragment @see FRAGMENT_*
* @param key key
* @param defaultValue default value
* @return value
*/
public String getContextWithDefault(String fragment, String key, String defaultValue) {
Map<String, String> fragmentContext = getFragmentContext(fragment);
if (fragmentContext == null) {
return defaultValue;
}
MetadataMapValue metadataMapValue = (MetadataMapValue) metadataValue;
metadataMapValue.iterateMapValues(new BiConsumer<String, MetadataValue>() {
@Override
public void accept(String s, MetadataValue metadataValue) {
if (metadataValue instanceof MetadataStringValue) {
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue;
if (metadataStringValue.getTransitiveType() == transitiveType) {
values.put(s, metadataStringValue.getStringValue());
}
}
}
});
return values;
String value = fragmentContext.get(key);
return StringUtils.isBlank(value) ? defaultValue : value;
}
private void putMapMetadataAsMap(MetadataType metadataType, String mapKey,
TransitiveType transitiveType, boolean caller, Map<String, String> values) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
for (Map.Entry<String, String> entry : values.entrySet()) {
metadataContainer.putMetadataMapValue(mapKey, entry.getKey(), entry.getValue(), transitiveType);
/**
* Get context with fragment.
*
* @param fragment @see FRAGMENT_*
* @param key key
* @return value
*/
public String getContext(String fragment, String key) {
Map<String, String> fragmentContext = getFragmentContext(fragment);
if (fragmentContext == null) {
return null;
}
return fragmentContext.get(key);
}
/**
* Put context with fragment DISPOSABLE.
*
* @param key key
* @param value value
*/
public void putContext(String key, String value) {
putContext(FRAGMENT_DISPOSABLE, key, value);
}
/**
* Put context with fragment.
*
* @param fragment @see FRAGMENT_*
* @param key key
* @param value value
*/
public void putContext(String fragment, String key, String value) {
Map<String, String> values = new HashMap<>(1);
values.put(key, value);
putFragmentContext(fragment, values);
}
public Map<String, String> getDisposableMetadata() {
@ -208,40 +243,32 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
return getFragmentContext(FRAGMENT_APPLICATION);
}
public Map<String, String> getCustomMetadata() {
Map<String, String> transitiveMetadata = this.getTransitiveMetadata();
Map<String, String> disposableMetadata = this.getDisposableMetadata();
Map<String, String> customMetadata = new HashMap<>();
// Clean up one-time metadata coming from upstream .
transitiveMetadata.forEach((key, value) -> {
if (!disposableMetadata.containsKey(key)) {
customMetadata.put(key, value);
}
});
return Collections.unmodifiableMap(customMetadata);
public Map<String, String> getTransHeaders() {
return getFragmentContext(FRAGMENT_RAW_TRANSHEADERS);
}
public Map<String, String> getTransHeaders() {
return this.getFragmentContext(FRAGMENT_RAW_TRANSHEADERS);
public void setTransHeaders(String key, String value) {
putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
}
public Map<String, String> getTransHeadersKV() {
return getFragmentContext(FRAGMENT_RAW_TRANSHEADERS_KV);
}
public void setTransHeadersKV(String key, String value) {
putContext(FRAGMENT_RAW_TRANSHEADERS_KV, key, value);
}
public Map<String, Object> getLoadbalancerMetadata() {
MetadataContainer metadataContainer = getMetadataContainer(MetadataType.CUSTOM, false);
MetadataValue metadataValue = metadataContainer.getMetadataValue(FRAGMENT_LB_METADATA);
Map<String, Object> values = new HashMap<>();
if (metadataValue instanceof MetadataMapValue) {
MetadataMapValue metadataMapValue = (MetadataMapValue) metadataValue;
metadataMapValue.iterateMapValues(new BiConsumer<String, MetadataValue>() {
@Override
public void accept(String s, MetadataValue metadataValue) {
if (metadataValue instanceof MetadataObjectValue) {
Optional<?> objectValue = ((MetadataObjectValue<?>) metadataValue).getObjectValue();
objectValue.ifPresent(o -> values.put(s, o));
}
metadataMapValue.iterateMapValues((s, metadataValue1) -> {
if (metadataValue1 instanceof MetadataObjectValue) {
Optional<?> objectValue = ((MetadataObjectValue<?>) metadataValue1).getObjectValue();
objectValue.ifPresent(o -> values.put(s, o));
}
});
}
@ -253,18 +280,6 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
metadataContainer.putMetadataMapObjectValue(FRAGMENT_LB_METADATA, key, value);
}
public void setUpstreamDisposableMetadata(Map<String, String> upstreamDisposableMetadata) {
putFragmentContext(FRAGMENT_UPSTREAM_DISPOSABLE, Collections.unmodifiableMap(upstreamDisposableMetadata));
}
public void setTransHeadersKV(String key, String value) {
putContext(FRAGMENT_RAW_TRANSHEADERS_KV, key, value);
}
public void setTransHeaders(String key, String value) {
putContext(FRAGMENT_RAW_TRANSHEADERS, key, value);
}
public Map<String, String> getFragmentContext(String fragment) {
switch (fragment) {
case FRAGMENT_TRANSITIVE:
@ -288,24 +303,6 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
}
}
public String getContext(String fragment, String key, String defaultValue) {
return getFragmentContext(fragment).getOrDefault(key, defaultValue);
}
public String getContext(String fragment, String key) {
Map<String, String> fragmentContext = getFragmentContext(fragment);
if (fragmentContext == null) {
return null;
}
return fragmentContext.get(key);
}
public void putContext(String fragment, String key, String value) {
Map<String, String> values = new HashMap<>();
values.put(key, value);
putFragmentContext(fragment, values);
}
public void putFragmentContext(String fragment, Map<String, String> context) {
switch (fragment) {
case FRAGMENT_TRANSITIVE:
@ -314,6 +311,9 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
case FRAGMENT_DISPOSABLE:
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, false, context);
break;
case FRAGMENT_NONE:
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.NONE, false, context);
break;
case FRAGMENT_UPSTREAM_DISPOSABLE:
putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.DISPOSABLE, true, context);
break;
@ -338,9 +338,51 @@ public class MetadataContext extends com.tencent.polaris.metadata.core.manager.M
}
}
public void putFragmentContext(String fragment, String key, String value) {
Map<String, String> context = new HashMap<>(1);
context.put(key, value);
putFragmentContext(fragment, context);
private Map<String, String> getMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
Map<String, String> values = new HashMap<>();
metadataContainer.iterateMetadataValues((s, metadataValue) -> {
if (metadataValue instanceof MetadataStringValue) {
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue;
if (metadataStringValue.getTransitiveType() == transitiveType) {
values.put(s, metadataStringValue.getStringValue());
}
}
});
return values;
}
private Map<String, String> getMapMetadataAsMap(MetadataType metadataType, String mapKey, TransitiveType transitiveType, boolean caller) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
Map<String, String> values = new HashMap<>();
MetadataValue metadataValue = metadataContainer.getMetadataValue(mapKey);
if (!(metadataValue instanceof MetadataMapValue)) {
return values;
}
MetadataMapValue metadataMapValue = (MetadataMapValue) metadataValue;
metadataMapValue.iterateMapValues((s, metadataValue1) -> {
if (metadataValue1 instanceof MetadataStringValue) {
MetadataStringValue metadataStringValue = (MetadataStringValue) metadataValue1;
if (metadataStringValue.getTransitiveType() == transitiveType) {
values.put(s, metadataStringValue.getStringValue());
}
}
});
return values;
}
private void putMetadataAsMap(MetadataType metadataType, TransitiveType transitiveType, boolean caller, Map<String, String> values) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
for (Map.Entry<String, String> entry : values.entrySet()) {
metadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), transitiveType);
}
}
private void putMapMetadataAsMap(MetadataType metadataType, String mapKey,
TransitiveType transitiveType, boolean caller, Map<String, String> values) {
MetadataContainer metadataContainer = getMetadataContainer(metadataType, caller);
for (Map.Entry<String, String> entry : values.entrySet()) {
metadataContainer.putMetadataMapValue(mapKey, entry.getKey(), entry.getValue(), transitiveType);
}
}
}

@ -167,7 +167,6 @@ public final class MetadataContextHolder {
MetadataContainer callerCustomMetadataContainer = metadataManager.getMetadataContainer(MetadataType.CUSTOM, true);
if (CollectionUtils.isNotEmpty(dynamicDisposableMetadata)) {
for (Map.Entry<String, String> entry : dynamicDisposableMetadata.entrySet()) {
calleeCustomMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.NONE);
callerCustomMetadataContainer.putMetadataStringValue(entry.getKey(), entry.getValue(), TransitiveType.DISPOSABLE);
}
}

@ -60,9 +60,9 @@ public class ApplicationContextAwareUtils implements ApplicationContextAware {
return applicationContext.getEnvironment().getProperty(key);
}
LOGGER.warn("applicationContext is null, try to get property({}} from System.getenv or System.getProperty", key);
String property = System.getenv(key);
String property = System.getProperty(key);
if (StringUtils.isBlank(property)) {
property = System.getProperty(key);
property = System.getenv(key);
}
return property;
}
@ -78,9 +78,9 @@ public class ApplicationContextAwareUtils implements ApplicationContextAware {
return applicationContext.getEnvironment().getProperty(key, defaultValue);
}
LOGGER.warn("applicationContext is null, try to get property({}} from System.getenv or System.getProperty", key);
String property = System.getenv(key);
String property = System.getProperty(key);
if (StringUtils.isBlank(property)) {
property = System.getProperty(key, defaultValue);
property = System.getenv(key);
}
return property;
}

@ -24,11 +24,14 @@ import java.util.Map;
import com.tencent.cloud.common.metadata.MetadataContext;
import com.tencent.cloud.common.metadata.MetadataContextHolder;
import com.tencent.polaris.metadata.core.MetadataType;
import com.tencent.polaris.metadata.core.TransitiveType;
import org.springframework.tsf.core.entity.Tag;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_DISPOSABLE;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_NONE;
import static com.tencent.cloud.common.metadata.MetadataContext.FRAGMENT_TRANSITIVE;
public final class TsfContext {
static final int MAX_KEY_LENGTH = 32;
@ -56,7 +59,12 @@ public final class TsfContext {
for (Map.Entry<String, String> entry : tagMap.entrySet()) {
validateTag(entry.getKey(), entry.getValue());
}
tsfCoreContext.putMetadataAsMap(MetadataType.CUSTOM, transitive, false, tagMap);
if (transitive == TransitiveType.PASS_THROUGH) {
tsfCoreContext.putFragmentContext(FRAGMENT_TRANSITIVE, tagMap);
}
else {
tsfCoreContext.putFragmentContext(FRAGMENT_DISPOSABLE, tagMap);
}
}
public static void putTag(String key, String value, Tag.ControlFlag... flags) {
@ -89,6 +97,6 @@ public final class TsfContext {
catch (Throwable throwable) {
throw new RuntimeException("Failed to parse custom metadata", throwable);
}
tsfCoreContext.putMetadataAsMap(MetadataType.CUSTOM, TransitiveType.NONE, false, tagMap);
tsfCoreContext.putFragmentContext(FRAGMENT_NONE, tagMap);
}
}

@ -0,0 +1,492 @@
/*
* Tencent is pleased to support the open source community by making spring-cloud-tencent available.
*
* Copyright (C) 2021 Tencent. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* 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.tencent.cloud.common.metadata;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link MetadataContext}.
*
* @author Haotian Zhang
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = MetadataContextTest.TestApplication.class,
properties = {"spring.config.location = classpath:application-test.yml",
"spring.main.web-application-type = reactive"})
public class MetadataContextTest {
private MetadataContext metadataContext;
@BeforeEach
void setUp() {
metadataContext = new MetadataContext();
}
/**
* Test getting context value with default value when key exists in DISPOSABLE fragment.
* Scenario: When key exists, should return the actual value instead of default value.
*/
@Test
public void testGetContextWithDefault_WhenKeyExists_ShouldReturnActualValue() {
metadataContext.putContext("testKey", "testValue");
String result = metadataContext.getContextWithDefault("testKey", "defaultValue");
assertThat(result).isEqualTo("testValue");
}
/**
* Test getting context value with default value when key does not exist.
* Scenario: When key does not exist, should return the default value.
*/
@Test
public void testGetContextWithDefault_WhenKeyNotExists_ShouldReturnDefaultValue() {
String result = metadataContext.getContextWithDefault("nonExistentKey", "defaultValue");
assertThat(result).isEqualTo("defaultValue");
}
/**
* Test getting context value with default value when value is blank.
* Scenario: When value is blank (empty string), should return the default value.
*/
@Test
public void testGetContextWithDefault_WhenValueIsBlank_ShouldReturnDefaultValue() {
metadataContext.putContext("blankKey", "");
String result = metadataContext.getContextWithDefault("blankKey", "defaultValue");
assertThat(result).isEqualTo("defaultValue");
}
/**
* Test getting context value from DISPOSABLE fragment.
* Scenario: Should retrieve value from the default DISPOSABLE fragment.
*/
@Test
public void testGetContext_FromDisposableFragment_ShouldReturnValue() {
metadataContext.putContext("key1", "value1");
String result = metadataContext.getContext("key1");
assertThat(result).isEqualTo("value1");
}
/**
* Test getting context value when key does not exist.
* Scenario: When key does not exist, should return null.
*/
@Test
public void testGetContext_WhenKeyNotExists_ShouldReturnNull() {
String result = metadataContext.getContext("nonExistentKey");
assertThat(result).isNull();
}
/**
* Test getting context value with specified fragment and default value.
* Scenario: When key exists in specified fragment, should return actual value.
*/
@Test
public void testGetContextWithFragmentAndDefault_WhenKeyExists_ShouldReturnActualValue() {
metadataContext.putContext(MetadataContext.FRAGMENT_TRANSITIVE, "transitiveKey", "transitiveValue");
String result = metadataContext.getContextWithDefault(MetadataContext.FRAGMENT_TRANSITIVE, "transitiveKey", "default");
assertThat(result).isEqualTo("transitiveValue");
}
/**
* Test getting context value with specified fragment when key does not exist.
* Scenario: When key does not exist in specified fragment, should return default value.
*/
@Test
public void testGetContextWithFragmentAndDefault_WhenKeyNotExists_ShouldReturnDefaultValue() {
String result = metadataContext.getContextWithDefault(MetadataContext.FRAGMENT_TRANSITIVE, "nonExistent", "defaultValue");
assertThat(result).isEqualTo("defaultValue");
}
/**
* Test getting context value with specified fragment.
* Scenario: Should retrieve value from the specified fragment correctly.
*/
@Test
public void testGetContextWithFragment_ShouldReturnValue() {
metadataContext.putContext(MetadataContext.FRAGMENT_DISPOSABLE, "dispKey", "dispValue");
String result = metadataContext.getContext(MetadataContext.FRAGMENT_DISPOSABLE, "dispKey");
assertThat(result).isEqualTo("dispValue");
}
/**
* Test putting context value into default DISPOSABLE fragment.
* Scenario: Value should be stored in DISPOSABLE fragment and retrievable.
*/
@Test
public void testPutContext_ToDefaultFragment_ShouldStoreValue() {
metadataContext.putContext("newKey", "newValue");
Map<String, String> disposableMetadata = metadataContext.getDisposableMetadata();
assertThat(disposableMetadata).containsEntry("newKey", "newValue");
}
/**
* Test putting context value into specified fragment.
* Scenario: Value should be stored in the specified fragment correctly.
*/
@Test
public void testPutContext_ToSpecifiedFragment_ShouldStoreValue() {
metadataContext.putContext(MetadataContext.FRAGMENT_TRANSITIVE, "transKey", "transValue");
Map<String, String> transitiveMetadata = metadataContext.getTransitiveMetadata();
assertThat(transitiveMetadata).containsEntry("transKey", "transValue");
}
/**
* Test setting and getting disposable metadata.
* Scenario: Should correctly store and retrieve multiple key-value pairs in disposable metadata.
*/
@Test
public void testSetAndGetDisposableMetadata_ShouldWorkCorrectly() {
Map<String, String> metadata = new HashMap<>();
metadata.put("key1", "value1");
metadata.put("key2", "value2");
metadataContext.setDisposableMetadata(metadata);
Map<String, String> result = metadataContext.getDisposableMetadata();
assertThat(result).hasSize(2);
assertThat(result).containsEntry("key1", "value1");
assertThat(result).containsEntry("key2", "value2");
}
/**
* Test setting and getting transitive metadata.
* Scenario: Should correctly store and retrieve transitive metadata that passes through service calls.
*/
@Test
public void testSetAndGetTransitiveMetadata_ShouldWorkCorrectly() {
Map<String, String> metadata = new HashMap<>();
metadata.put("trans1", "transValue1");
metadata.put("trans2", "transValue2");
metadataContext.setTransitiveMetadata(metadata);
Map<String, String> result = metadataContext.getTransitiveMetadata();
assertThat(result).hasSize(2);
assertThat(result).containsEntry("trans1", "transValue1");
assertThat(result).containsEntry("trans2", "transValue2");
}
/**
* Test getting application metadata.
* Scenario: Should retrieve application-level metadata from APPLICATION fragment.
*/
@Test
public void testGetApplicationMetadata_ShouldReturnApplicationFragmentData() {
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION, Map.of("appKey", "appValue"));
Map<String, String> result = metadataContext.getApplicationMetadata();
assertThat(result).containsEntry("appKey", "appValue");
}
/**
* Test setting and getting trans headers.
* Scenario: Should store header keys that need to be transmitted from upstream to downstream.
*/
@Test
public void testSetAndGetTransHeaders_ShouldWorkCorrectly() {
metadataContext.setTransHeaders("headerKey", "headerValue");
Map<String, String> result = metadataContext.getTransHeaders();
assertThat(result).containsEntry("headerKey", "headerValue");
}
/**
* Test setting and getting trans headers key-value pairs.
* Scenario: Should store header key-value pairs for transmission between services.
*/
@Test
public void testSetAndGetTransHeadersKV_ShouldWorkCorrectly() {
metadataContext.setTransHeadersKV("kvKey", "kvValue");
Map<String, String> result = metadataContext.getTransHeadersKV();
assertThat(result).containsEntry("kvKey", "kvValue");
}
/**
* Test setting and getting loadbalancer metadata.
* Scenario: Should store and retrieve object values for load balancer decisions.
*/
@Test
public void testSetAndGetLoadbalancerMetadata_ShouldWorkCorrectly() {
metadataContext.setLoadbalancer("lbKey", "lbValue");
metadataContext.setLoadbalancer("lbIntKey", 100);
Map<String, Object> result = metadataContext.getLoadbalancerMetadata();
assertThat(result).containsEntry("lbKey", "lbValue");
assertThat(result).containsEntry("lbIntKey", 100);
}
/**
* Test getting fragment context for TRANSITIVE fragment.
* Scenario: Should return metadata that passes through all service calls.
*/
@Test
public void testGetFragmentContext_ForTransitiveFragment_ShouldReturnCorrectData() {
Map<String, String> transitiveData = new HashMap<>();
transitiveData.put("passThrough1", "value1");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE, transitiveData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_TRANSITIVE);
assertThat(result).containsEntry("passThrough1", "value1");
}
/**
* Test getting fragment context for DISPOSABLE fragment.
* Scenario: Should return metadata that is disposed after single use.
*/
@Test
public void testGetFragmentContext_ForDisposableFragment_ShouldReturnCorrectData() {
Map<String, String> disposableData = new HashMap<>();
disposableData.put("disposeKey", "disposeValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE, disposableData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_DISPOSABLE);
assertThat(result).containsEntry("disposeKey", "disposeValue");
}
/**
* Test getting fragment context for UPSTREAM_DISPOSABLE fragment.
* Scenario: Should return disposable metadata from the caller/upstream service.
*/
@Test
public void testGetFragmentContext_ForUpstreamDisposableFragment_ShouldReturnCorrectData() {
Map<String, String> upstreamData = new HashMap<>();
upstreamData.put("upstreamKey", "upstreamValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE, upstreamData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE);
assertThat(result).containsEntry("upstreamKey", "upstreamValue");
}
/**
* Test getting fragment context for APPLICATION fragment.
* Scenario: Should return application-level disposable metadata.
*/
@Test
public void testGetFragmentContext_ForApplicationFragment_ShouldReturnCorrectData() {
Map<String, String> appData = new HashMap<>();
appData.put("applicationKey", "applicationValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION, appData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_APPLICATION);
assertThat(result).containsEntry("applicationKey", "applicationValue");
}
/**
* Test getting fragment context for APPLICATION_NONE fragment.
* Scenario: Should return application metadata with NONE transitive type.
*/
@Test
public void testGetFragmentContext_ForApplicationNoneFragment_ShouldReturnCorrectData() {
Map<String, String> appNoneData = new HashMap<>();
appNoneData.put("appNoneKey", "appNoneValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE, appNoneData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE);
assertThat(result).containsEntry("appNoneKey", "appNoneValue");
}
/**
* Test getting fragment context for UPSTREAM_APPLICATION fragment.
* Scenario: Should return application-level metadata from the caller/upstream service.
*/
@Test
public void testGetFragmentContext_ForUpstreamApplicationFragment_ShouldReturnCorrectData() {
Map<String, String> upstreamAppData = new HashMap<>();
upstreamAppData.put("upstreamAppKey", "upstreamAppValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_APPLICATION, upstreamAppData);
Map<String, String> result = metadataContext.getFragmentContext(MetadataContext.FRAGMENT_UPSTREAM_APPLICATION);
assertThat(result).containsEntry("upstreamAppKey", "upstreamAppValue");
}
/**
* Test getting fragment context for custom fragment.
* Scenario: Should handle custom fragment names using the default case in switch statement.
*/
@Test
public void testGetFragmentContext_ForCustomFragment_ShouldReturnCorrectData() {
Map<String, String> customData = new HashMap<>();
customData.put("customKey", "customValue");
metadataContext.putFragmentContext("custom-fragment", customData);
Map<String, String> result = metadataContext.getFragmentContext("custom-fragment");
assertThat(result).containsEntry("customKey", "customValue");
}
/**
* Test putting fragment context with NONE fragment type.
* Scenario: Should store metadata with NONE transitive type that won't be passed to downstream.
*/
@Test
public void testPutFragmentContext_ForNoneFragment_ShouldStoreCorrectly() {
Map<String, String> noneData = new HashMap<>();
noneData.put("noneKey", "noneValue");
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_NONE, noneData);
// NONE fragment doesn't have a direct getter, verify through internal state
// The data should be stored with TransitiveType.NONE
assertThat(noneData).containsEntry("noneKey", "noneValue");
}
/**
* Test static method setLocalService.
* Scenario: Should update the LOCAL_SERVICE static field.
*/
@Test
public void testSetLocalService_ShouldUpdateStaticField() {
String originalService = MetadataContext.LOCAL_SERVICE;
MetadataContext.setLocalService("newServiceName");
assertThat(MetadataContext.LOCAL_SERVICE).isEqualTo("newServiceName");
// Restore original value
MetadataContext.setLocalService(originalService);
}
/**
* Test static method setLocalNamespace.
* Scenario: Should update the LOCAL_NAMESPACE static field.
*/
@Test
public void testSetLocalNamespace_ShouldUpdateStaticField() {
String originalNamespace = MetadataContext.LOCAL_NAMESPACE;
MetadataContext.setLocalNamespace("newNamespace");
assertThat(MetadataContext.LOCAL_NAMESPACE).isEqualTo("newNamespace");
// Restore original value
MetadataContext.setLocalNamespace(originalNamespace);
}
/**
* Test fragment constants are defined correctly.
* Scenario: All fragment constant values should be non-null and match expected string values.
*/
@Test
public void testFragmentConstants_ShouldHaveCorrectValues() {
assertThat(MetadataContext.FRAGMENT_TRANSITIVE).isEqualTo("transitive");
assertThat(MetadataContext.FRAGMENT_DISPOSABLE).isEqualTo("disposable");
assertThat(MetadataContext.FRAGMENT_NONE).isEqualTo("none");
assertThat(MetadataContext.FRAGMENT_UPSTREAM_DISPOSABLE).isEqualTo("upstream-disposable");
assertThat(MetadataContext.FRAGMENT_APPLICATION).isEqualTo("application");
assertThat(MetadataContext.FRAGMENT_APPLICATION_NONE).isEqualTo("application-none");
assertThat(MetadataContext.FRAGMENT_UPSTREAM_APPLICATION).isEqualTo("upstream-application");
assertThat(MetadataContext.FRAGMENT_RAW_TRANSHEADERS).isEqualTo("trans-headers");
assertThat(MetadataContext.FRAGMENT_RAW_TRANSHEADERS_KV).isEqualTo("trans-headers-kv");
assertThat(MetadataContext.FRAGMENT_LB_METADATA).isEqualTo("load-balance-metadata");
}
/**
* Test multiple values can be stored and retrieved from the same fragment.
* Scenario: Should support storing multiple key-value pairs in a single fragment.
*/
@Test
public void testMultipleValuesInSameFragment_ShouldAllBeRetrievable() {
metadataContext.putContext("key1", "value1");
metadataContext.putContext("key2", "value2");
metadataContext.putContext("key3", "value3");
Map<String, String> result = metadataContext.getDisposableMetadata();
assertThat(result).hasSize(3);
assertThat(result).containsEntry("key1", "value1");
assertThat(result).containsEntry("key2", "value2");
assertThat(result).containsEntry("key3", "value3");
}
/**
* Test overwriting existing value in fragment.
* Scenario: When putting a value with existing key, should overwrite the previous value.
*/
@Test
public void testOverwriteExistingValue_ShouldUpdateValue() {
metadataContext.putContext("overwriteKey", "originalValue");
metadataContext.putContext("overwriteKey", "newValue");
String result = metadataContext.getContext("overwriteKey");
assertThat(result).isEqualTo("newValue");
}
/**
* Test getting loadbalancer metadata when no data is set.
* Scenario: Should return empty map when no loadbalancer metadata has been set.
*/
@Test
public void testGetLoadbalancerMetadata_WhenEmpty_ShouldReturnEmptyMap() {
Map<String, Object> result = metadataContext.getLoadbalancerMetadata();
assertThat(result).isNotNull();
assertThat(result).isEmpty();
}
/**
* Test LOCAL_NAMESPACE and LOCAL_SERVICE static initialization.
* Scenario: Static fields should be initialized from application properties.
*/
@Test
public void testStaticInitialization_ShouldLoadFromProperties() {
assertThat(MetadataContext.LOCAL_NAMESPACE).isNotNull();
assertThat(MetadataContext.LOCAL_SERVICE).isNotNull();
}
@SpringBootApplication
protected static class TestApplication {
}
}

@ -287,7 +287,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
// priority: namespace id(tsf) > namespace name(polaris)
String routeNamespace = StringUtils.isBlank(contextRoute.getNamespaceId()) ?
contextRoute.getNamespace() : contextRoute.getNamespaceId();
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
metadataContext.putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, routeNamespace);
}
URI requestUri = URI.create("lb://" + contextRoute.getService() + apis[1]);
@ -341,7 +341,7 @@ public class ContextGatewayFilter implements GatewayFilter, Ordered {
if (metadataContext != null) {
// get unit ns
String routeNamespace = TencentUnitContext.getSystemTag(TencentUnitContext.CLOUD_SPACE_TARGET_NAMESPACE_ID);
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
metadataContext.putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, routeNamespace);
}
URI requestUri = URI.create("lb://" + contextRoute.getService() + apis[1]);

@ -257,7 +257,7 @@ public class ContextGatewayPropertiesManager {
String service = contextRoute.getService();
if (StringUtils.isNotEmpty(namespace) && StringUtils.isNotEmpty(service)) {
logger.info("[{},{}] eager-load start", namespace, service);
MetadataContextHolder.get().putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataContextHolder.get().putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, namespace);
if (polarisDiscoveryClient != null) {

@ -184,7 +184,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
serviceName = parts[1];
}
try {
MetadataContextHolder.get().putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataContextHolder.get().putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, namespace);
ReactorLoadBalancer<ServiceInstance> loadBalancer = this.clientFactory.getInstance(serviceName,
ReactorServiceInstanceLoadBalancer.class);
@ -219,7 +219,7 @@ public class OAuthGatewayPlugin implements IGatewayPlugin<OAuthPlugin> {
}
finally {
// restore context
MetadataContextHolder.get().putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataContextHolder.get().putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, backupNamespace);
}
}

@ -63,13 +63,13 @@ public class UnitPolarisDiscoveryClient extends PolarisDiscoveryClient {
String namespace = TencentUnitContext.getStringRouteTag(TencentUnitContext.CLOUD_SPACE_ROUTE_TARGET_NAMESPACE_ID);
MetadataContext metadataContext = MetadataContextHolder.get();
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
metadataContext.putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, namespace);
return delegate.getInstances(service);
}
else {
MetadataContext metadataContext = MetadataContextHolder.get();
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
metadataContext.putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, parts[0]);
return delegate.getInstances(parts[1]);

@ -461,7 +461,7 @@ public final class SpringCloudUnitUtils {
setUnitContext(unitId, namespace, serviceName);
// 设置治理 ns
MetadataContext metadataContext = MetadataContextHolder.get();
metadataContext.putFragmentContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
metadataContext.putContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, namespace.getId());
return true;
}

@ -80,7 +80,8 @@ public class EnhancedFeignClient implements Client {
URI serviceUrl = url.resolve(request.requestTemplate().url());
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
String governanceNamespace = MetadataContextHolder.get()
.getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()

@ -77,7 +77,8 @@ public class EnhancedRestTemplateBlockingLoadBalancerClientInterceptor {
serviceUrl = ((ServiceRequestWrapper) httpRequest).getRequest().getURI();
}
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
String governanceNamespace = MetadataContextHolder.get()
.getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()

@ -81,7 +81,7 @@ public class EnhancedGatewayGlobalFilter implements GlobalFilter, Ordered {
metadataContext = MetadataContextHolder.get();
}
String governanceNamespace = metadataContext.getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
String governanceNamespace = metadataContext.getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);

@ -60,8 +60,8 @@ public class EnhancedWebClientExchangeFilterFunction implements ExchangeFilterFu
public Mono<ClientResponse> filter(ClientRequest originRequest, ExchangeFunction next) {
EnhancedPluginContext enhancedPluginContext = EnhancedPluginUtils.createEnhancedPluginContext();
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
String governanceNamespace = MetadataContextHolder.get()
.getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE, MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
.httpHeaders(originRequest.headers())

@ -136,8 +136,8 @@ public final class PolarisEnhancedPluginUtils {
@Nullable String calleeServiceName, @Nullable String calleeHost, @Nullable Integer calleePort,
URI uri, @Nullable Integer statusCode, long delay, @Nullable Throwable exception) {
String governanceNamespace = MetadataContextHolder.get().getContext(MetadataContext.FRAGMENT_APPLICATION_NONE,
MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
String governanceNamespace = MetadataContextHolder.get()
.getContextWithDefault(MetadataContext.FRAGMENT_APPLICATION_NONE, MetadataConstant.POLARIS_TARGET_NAMESPACE, MetadataContext.LOCAL_NAMESPACE);
ServiceKey calleeServiceKey = new ServiceKey(governanceNamespace, StringUtils.isBlank(calleeServiceName) ? uri.getHost() : calleeServiceName);
ServiceKey callerServiceKey = new ServiceKey(MetadataContext.LOCAL_NAMESPACE, MetadataContext.LOCAL_SERVICE);

Loading…
Cancel
Save