BitoAgent commented on code in PR #13786:
URL: https://github.com/apache/dubbo/pull/13786#discussion_r1543381768
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -221,7 +221,7 @@ public AbstractInterfaceConfig(ModuleModel moduleModel) {
/**
* The url of the reference service
*/
- protected final transient List<URL> urls = new ArrayList<URL>();
+ protected final transient List<URL> urls = new ArrayList<>();
Review Comment:
**Suggestion**: Utilize the diamond operator for initializing the ArrayList
to improve code readability. <br> **Code Suggestion**:
```
+ protected final transient List<URL> urls = new ArrayList<>();
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -353,14 +353,14 @@
// refresh MethodConfigs
List<MethodConfig> methodConfigs = this.getMethods();
- if (methodConfigs != null && methodConfigs.size() > 0) {
+ if (methodConfigs != null && !methodConfigs.isEmpty()) {
Review Comment:
**Suggestion**: Replace size() > 0 check with !isEmpty() for clarity and
performance. <br> **Code Suggestion**:
```
+ if (methodConfigs != null && !methodConfigs.isEmpty()) {
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -252,7 +252,7 @@
}
if (CollectionUtils.isNotEmpty(this.registries)) {
this.registries.forEach(registryConfig -> {
- if (registryConfig.getScopeModel() != applicationModel) {
+ if (registryConfig != null && registryConfig.getScopeModel()
!= applicationModel) {
Review Comment:
**Suggestion**: Add null check for registryConfig to avoid potential
NullPointerException. <br> **Code Suggestion**:
```
+ if (registryConfig != null &&
registryConfig.getScopeModel() != applicationModel) {
```
##########
dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java:
##########
@@ -20,7 +20,6 @@
import org.apache.dubbo.remoting.http12.exception.DecodeException;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
Review Comment:
**Performance Issue**: Unused import 'java.io.ByteArrayOutputStream' should
be removed to keep code clean. <br> **Fix**: Remove the unused import statement
to clean up the code. <br> **Code Suggestion**:
```
-import java.io.ByteArrayOutputStream;
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -353,14 +353,14 @@
// refresh MethodConfigs
List<MethodConfig> methodConfigs = this.getMethods();
- if (methodConfigs != null && methodConfigs.size() > 0) {
+ if (methodConfigs != null && !methodConfigs.isEmpty()) {
Review Comment:
**Optimization Issue**: Replacing 'methodConfigs.size() > 0' with
'!methodConfigs.isEmpty()' improves readability and is more idiomatic. <br>
**Fix**: Use '!methodConfigs.isEmpty()' to check if the list is not empty,
which is more direct and readable. <br> **Code Suggestion**:
```
- if (methods != null && methods.size() > 0) {
+ if (methods != null && !methods.isEmpty()) {
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -420,7 +420,7 @@
}
private ArgumentConfig getArgumentByIndex(MethodConfig methodConfig, int
argIndex) {
- if (methodConfig.getArguments() != null &&
methodConfig.getArguments().size() > 0) {
+ if (methodConfig.getArguments() != null &&
!methodConfig.getArguments().isEmpty()) {
Review Comment:
**Suggestion**: Simplify collection emptiness check using !isEmpty(). <br>
**Code Suggestion**:
```
+ if (methodConfig.getArguments() != null &&
!methodConfig.getArguments().isEmpty()) {
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -252,7 +252,7 @@
}
if (CollectionUtils.isNotEmpty(this.registries)) {
this.registries.forEach(registryConfig -> {
- if (registryConfig.getScopeModel() != applicationModel) {
+ if (registryConfig != null && registryConfig.getScopeModel()
!= applicationModel) {
Review Comment:
**Performance Issue**: Adding null check for 'registryConfig' before
accessing its methods prevents potential 'NullPointerException'. <br> **Fix**:
Add a null check for 'registryConfig' to ensure safety when accessing its
'getScopeModel' method. <br> **Code Suggestion**:
```
- if (registryConfig.getScopeModel() != applicationModel) {
+ if (registryConfig != null &&
registryConfig.getScopeModel() != applicationModel) {
```
##########
dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java:
##########
@@ -16,123 +16,103 @@
*/
package org.apache.dubbo.rpc.protocol.tri.h12.grpc;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.io.StreamUtils;
+import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.remoting.http12.exception.DecodeException;
import org.apache.dubbo.remoting.http12.exception.EncodeException;
import org.apache.dubbo.remoting.http12.message.HttpMessageCodec;
import org.apache.dubbo.remoting.http12.message.MediaType;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.MethodDescriptor;
+import org.apache.dubbo.rpc.model.PackableMethod;
+import org.apache.dubbo.rpc.model.PackableMethodFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
-import com.google.protobuf.Message;
-
-import static
org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static
org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY;
public class GrpcCompositeCodec implements HttpMessageCodec {
- private final ProtobufHttpMessageCodec protobufHttpMessageCodec;
+ private static final String PACKABLE_METHOD_CACHE =
"PACKABLE_METHOD_CACHE";
- private final WrapperHttpMessageCodec wrapperHttpMessageCodec;
+ private final URL url;
- public GrpcCompositeCodec(
- ProtobufHttpMessageCodec protobufHttpMessageCodec,
WrapperHttpMessageCodec wrapperHttpMessageCodec) {
- this.protobufHttpMessageCodec = protobufHttpMessageCodec;
- this.wrapperHttpMessageCodec = wrapperHttpMessageCodec;
- }
+ private final FrameworkModel frameworkModel;
+
+ private final String mediaType;
- public void setEncodeTypes(Class<?>[] encodeTypes) {
- this.wrapperHttpMessageCodec.setEncodeTypes(encodeTypes);
+ private PackableMethod packableMethod;
+
+ public GrpcCompositeCodec(URL url, FrameworkModel frameworkModel, String
mediaType) {
+ this.url = url;
+ this.frameworkModel = frameworkModel;
+ this.mediaType = mediaType;
}
- public void setDecodeTypes(Class<?>[] decodeTypes) {
- this.wrapperHttpMessageCodec.setDecodeTypes(decodeTypes);
+ public void loadPackableMethod(MethodDescriptor methodDescriptor) {
+ if (methodDescriptor instanceof PackableMethod) {
+ packableMethod = (PackableMethod) methodDescriptor;
+ return;
+ }
+ Map<MethodDescriptor, PackableMethod> cacheMap =
(Map<MethodDescriptor, PackableMethod>) url.getServiceModel()
+ .getServiceMetadata()
+ .getAttributeMap()
+ .computeIfAbsent(PACKABLE_METHOD_CACHE, k -> new
ConcurrentHashMap<>());
+ packableMethod = cacheMap.computeIfAbsent(methodDescriptor, md ->
frameworkModel
+ .getExtensionLoader(PackableMethodFactory.class)
+
.getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel())
+ .getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY))
+ .create(methodDescriptor, url, mediaType));
}
@Override
public void encode(OutputStream outputStream, Object data, Charset
charset) throws EncodeException {
- // protobuf
- // TODO int compressed =
Identity.MESSAGE_ENCODING.equals(requestMetadata.compressor.getMessageEncoding())
? 0 :
- // 1;
try {
- int compressed = 0;
- outputStream.write(compressed);
- if (isProtobuf(data)) {
- ProtobufWriter.write(protobufHttpMessageCodec, outputStream,
data);
- return;
- }
- // wrapper
- wrapperHttpMessageCodec.encode(outputStream, data);
- } catch (IOException e) {
+ outputStream.write(0);
+ byte[] bytes = packableMethod.packResponse(data);
+ writeLength(outputStream, bytes.length);
+ outputStream.write(bytes);
+ } catch (Exception e) {
throw new EncodeException(e);
}
}
@Override
public Object decode(InputStream inputStream, Class<?> targetType, Charset
charset) throws DecodeException {
- if (isProtoClass(targetType)) {
- return protobufHttpMessageCodec.decode(inputStream, targetType,
charset);
+ try {
+ byte[] data = StreamUtils.readBytes(inputStream);
+ return packableMethod.parseRequest(data);
+ } catch (Exception e) {
+ throw new DecodeException(e);
}
- return wrapperHttpMessageCodec.decode(inputStream, targetType,
charset);
}
@Override
public Object[] decode(InputStream inputStream, Class<?>[] targetTypes,
Charset charset) throws DecodeException {
- if (targetTypes.length > 1) {
- return wrapperHttpMessageCodec.decode(inputStream, targetTypes,
charset);
- }
- return HttpMessageCodec.super.decode(inputStream, targetTypes,
charset);
- }
-
- private static void writeLength(OutputStream outputStream, int length) {
- try {
- outputStream.write(((length >> 24) & 0xFF));
- outputStream.write(((length >> 16) & 0xFF));
- outputStream.write(((length >> 8) & 0xFF));
- outputStream.write((length & 0xFF));
- } catch (IOException e) {
- throw new EncodeException(e);
+ Object message = decode(inputStream, ArrayUtils.isEmpty(targetTypes) ?
null : targetTypes[0], charset);
+ if (message instanceof Object[]) {
+ return (Object[]) message;
}
+ return new Object[] {message};
}
@Override
public MediaType mediaType() {
return MediaType.APPLICATION_GRPC;
}
- private static boolean isProtobuf(Object data) {
- if (data == null) {
- return false;
- }
- return isProtoClass(data.getClass());
- }
-
- private static boolean isProtoClass(Class<?> clazz) {
- while (clazz != Object.class && clazz != null) {
- Class<?>[] interfaces = clazz.getInterfaces();
- if (interfaces.length > 0) {
- for (Class<?> clazzInterface : interfaces) {
- if
(PROTOBUF_MESSAGE_CLASS_NAME.equalsIgnoreCase(clazzInterface.getName())) {
- return true;
- }
- }
- }
- clazz = clazz.getSuperclass();
- }
- return false;
- }
-
- /**
- * lazy init protobuf class
- */
- private static class ProtobufWriter {
-
- private static void write(HttpMessageCodec codec, OutputStream
outputStream, Object data) {
- int serializedSize = ((Message) data).getSerializedSize();
- // write length
- writeLength(outputStream, serializedSize);
- codec.encode(outputStream, data);
- }
+ private void writeLength(OutputStream outputStream, int length) throws
IOException {
+ outputStream.write(((length >> 24) & 0xFF));
+ outputStream.write(((length >> 16) & 0xFF));
+ outputStream.write(((length >> 8) & 0xFF));
+ outputStream.write((length & 0xFF));
Review Comment:
**Suggestion**: Implement writeLength method directly in GrpcCompositeCodec
to encapsulate byte length writing logic. <br> **Code Suggestion**:
```
+ outputStream.write(((length >> 24) & 0xFF));
+ outputStream.write(((length >> 16) & 0xFF));
+ outputStream.write(((length >> 8) & 0xFF));
+ outputStream.write((length & 0xFF));
```
##########
dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java:
##########
@@ -46,8 +45,6 @@
private int requiredLength;
- private InputStream dataHeader = new ByteArrayInputStream(new byte[0]);
-
public LengthFieldStreamingDecoder() {
this(4);
}
Review Comment:
**Performance Issue**: The 'dataHeader' InputStream field is declared but
never used in the 'LengthFieldStreamingDecoder' class. Unused fields can lead
to confusion and should be removed if they are not planned to be used. <br>
**Fix**: Remove the 'dataHeader' field as it is not used anywhere in the class.
<br> **Code Suggestion**:
```
- private InputStream dataHeader = new ByteArrayInputStream(new byte[0]);
```
##########
dubbo-remoting/dubbo-remoting-http12/src/main/java/org/apache/dubbo/remoting/http12/message/LengthFieldStreamingDecoder.java:
##########
@@ -20,7 +20,6 @@
import org.apache.dubbo.remoting.http12.exception.DecodeException;
import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
Review Comment:
**Suggestion**: Remove unused import to clean up the code. <br> **Code
Suggestion**:
```
(Removal, no replacement needed)
```
##########
dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java:
##########
@@ -16,123 +16,103 @@
*/
package org.apache.dubbo.rpc.protocol.tri.h12.grpc;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.io.StreamUtils;
+import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.remoting.http12.exception.DecodeException;
import org.apache.dubbo.remoting.http12.exception.EncodeException;
import org.apache.dubbo.remoting.http12.message.HttpMessageCodec;
import org.apache.dubbo.remoting.http12.message.MediaType;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.MethodDescriptor;
+import org.apache.dubbo.rpc.model.PackableMethod;
+import org.apache.dubbo.rpc.model.PackableMethodFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
-import com.google.protobuf.Message;
-
-import static
org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static
org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY;
public class GrpcCompositeCodec implements HttpMessageCodec {
- private final ProtobufHttpMessageCodec protobufHttpMessageCodec;
+ private static final String PACKABLE_METHOD_CACHE =
"PACKABLE_METHOD_CACHE";
- private final WrapperHttpMessageCodec wrapperHttpMessageCodec;
+ private final URL url;
- public GrpcCompositeCodec(
- ProtobufHttpMessageCodec protobufHttpMessageCodec,
WrapperHttpMessageCodec wrapperHttpMessageCodec) {
- this.protobufHttpMessageCodec = protobufHttpMessageCodec;
- this.wrapperHttpMessageCodec = wrapperHttpMessageCodec;
- }
+ private final FrameworkModel frameworkModel;
+
+ private final String mediaType;
- public void setEncodeTypes(Class<?>[] encodeTypes) {
- this.wrapperHttpMessageCodec.setEncodeTypes(encodeTypes);
+ private PackableMethod packableMethod;
+
+ public GrpcCompositeCodec(URL url, FrameworkModel frameworkModel, String
mediaType) {
+ this.url = url;
+ this.frameworkModel = frameworkModel;
+ this.mediaType = mediaType;
}
- public void setDecodeTypes(Class<?>[] decodeTypes) {
- this.wrapperHttpMessageCodec.setDecodeTypes(decodeTypes);
+ public void loadPackableMethod(MethodDescriptor methodDescriptor) {
+ if (methodDescriptor instanceof PackableMethod) {
+ packableMethod = (PackableMethod) methodDescriptor;
+ return;
+ }
+ Map<MethodDescriptor, PackableMethod> cacheMap =
(Map<MethodDescriptor, PackableMethod>) url.getServiceModel()
+ .getServiceMetadata()
+ .getAttributeMap()
+ .computeIfAbsent(PACKABLE_METHOD_CACHE, k -> new
ConcurrentHashMap<>());
+ packableMethod = cacheMap.computeIfAbsent(methodDescriptor, md ->
frameworkModel
+ .getExtensionLoader(PackableMethodFactory.class)
+
.getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel())
+ .getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY))
+ .create(methodDescriptor, url, mediaType));
Review Comment:
**Optimization Issue**: Simplification of codec creation logic by directly
initializing GrpcCompositeCodec with necessary parameters instead of managing
separate codec instances. <br> **Fix**: Refactor the codec creation to use a
single GrpcCompositeCodec instance, simplifying the overall design and
improving maintainability. <br> **Code Suggestion**:
```
public class GrpcCompositeCodec implements HttpMessageCodec {
private final URL url;
private final FrameworkModel frameworkModel;
private final String mediaType;
private PackableMethod packableMethod;
public GrpcCompositeCodec(URL url, FrameworkModel frameworkModel,
String mediaType) {
this.url = url;
this.frameworkModel = frameworkModel;
this.mediaType = mediaType;
initialize();
}
private void initialize() {
// Initialization logic here
}
@Override
public void encode(OutputStream outputStream, Object data, Charset
charset) throws EncodeException {
...
}
@Override
public Object decode(InputStream inputStream, Class<?> targetType,
Charset charset) throws DecodeException {
...
}
...
}
```
##########
dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java:
##########
@@ -252,7 +252,7 @@
}
if (CollectionUtils.isNotEmpty(this.registries)) {
this.registries.forEach(registryConfig -> {
- if (registryConfig.getScopeModel() != applicationModel) {
+ if (registryConfig != null && registryConfig.getScopeModel()
!= applicationModel) {
Review Comment:
**Scalability Issue**: Adding a null check ('registryConfig != null')
before checking the scope model increases the robustness of the code. This
change prevents potential NullPointerExceptions, which can be critical in a
scalable system where registry configurations might be dynamically loaded or
unloaded, leading to situations where 'registryConfig' could be 'null'. <br>
**Fix**: The addition of the null check is a good practice. Ensure that all
similar instances in the codebase are also checked for null to maintain
consistency and prevent scalability issues related to dynamic configuration
changes. <br> **Code Suggestion**:
```
The addition of the null check is a good practice. Ensure that all similar
instances in the codebase are also checked for null to maintain consistency and
prevent scalability issues related to dynamic configuration changes.
```
##########
dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/h12/grpc/GrpcCompositeCodec.java:
##########
@@ -16,123 +16,103 @@
*/
package org.apache.dubbo.rpc.protocol.tri.h12.grpc;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.io.StreamUtils;
+import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.remoting.http12.exception.DecodeException;
import org.apache.dubbo.remoting.http12.exception.EncodeException;
import org.apache.dubbo.remoting.http12.message.HttpMessageCodec;
import org.apache.dubbo.remoting.http12.message.MediaType;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.MethodDescriptor;
+import org.apache.dubbo.rpc.model.PackableMethod;
+import org.apache.dubbo.rpc.model.PackableMethodFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
-import com.google.protobuf.Message;
-
-import static
org.apache.dubbo.common.constants.CommonConstants.PROTOBUF_MESSAGE_CLASS_NAME;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static
org.apache.dubbo.common.constants.CommonConstants.DUBBO_PACKABLE_METHOD_FACTORY;
public class GrpcCompositeCodec implements HttpMessageCodec {
- private final ProtobufHttpMessageCodec protobufHttpMessageCodec;
+ private static final String PACKABLE_METHOD_CACHE =
"PACKABLE_METHOD_CACHE";
- private final WrapperHttpMessageCodec wrapperHttpMessageCodec;
+ private final URL url;
- public GrpcCompositeCodec(
- ProtobufHttpMessageCodec protobufHttpMessageCodec,
WrapperHttpMessageCodec wrapperHttpMessageCodec) {
- this.protobufHttpMessageCodec = protobufHttpMessageCodec;
- this.wrapperHttpMessageCodec = wrapperHttpMessageCodec;
- }
+ private final FrameworkModel frameworkModel;
+
+ private final String mediaType;
- public void setEncodeTypes(Class<?>[] encodeTypes) {
- this.wrapperHttpMessageCodec.setEncodeTypes(encodeTypes);
+ private PackableMethod packableMethod;
+
+ public GrpcCompositeCodec(URL url, FrameworkModel frameworkModel, String
mediaType) {
+ this.url = url;
+ this.frameworkModel = frameworkModel;
+ this.mediaType = mediaType;
}
- public void setDecodeTypes(Class<?>[] decodeTypes) {
- this.wrapperHttpMessageCodec.setDecodeTypes(decodeTypes);
+ public void loadPackableMethod(MethodDescriptor methodDescriptor) {
+ if (methodDescriptor instanceof PackableMethod) {
+ packableMethod = (PackableMethod) methodDescriptor;
+ return;
+ }
+ Map<MethodDescriptor, PackableMethod> cacheMap =
(Map<MethodDescriptor, PackableMethod>) url.getServiceModel()
+ .getServiceMetadata()
+ .getAttributeMap()
+ .computeIfAbsent(PACKABLE_METHOD_CACHE, k -> new
ConcurrentHashMap<>());
+ packableMethod = cacheMap.computeIfAbsent(methodDescriptor, md ->
frameworkModel
+ .getExtensionLoader(PackableMethodFactory.class)
+
.getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel())
+ .getString(DUBBO_PACKABLE_METHOD_FACTORY, DEFAULT_KEY))
+ .create(methodDescriptor, url, mediaType));
}
@Override
public void encode(OutputStream outputStream, Object data, Charset
charset) throws EncodeException {
- // protobuf
- // TODO int compressed =
Identity.MESSAGE_ENCODING.equals(requestMetadata.compressor.getMessageEncoding())
? 0 :
- // 1;
try {
- int compressed = 0;
- outputStream.write(compressed);
- if (isProtobuf(data)) {
- ProtobufWriter.write(protobufHttpMessageCodec, outputStream,
data);
- return;
- }
- // wrapper
- wrapperHttpMessageCodec.encode(outputStream, data);
- } catch (IOException e) {
+ outputStream.write(0);
+ byte[] bytes = packableMethod.packResponse(data);
+ writeLength(outputStream, bytes.length);
+ outputStream.write(bytes);
Review Comment:
**Scalability Issue**: Refactoring to use a more modular and extensible
codec system, such as replacing specific codec implementations with a more
generic, pluggable mechanism, can significantly enhance the scalability of the
system. This allows for easier addition of new codecs and serialization
mechanisms without modifying the core logic, which is crucial for maintaining a
scalable, extensible system. <br> **Fix**: Implement a codec registry or
factory pattern that allows for runtime registration and retrieval of codecs.
This pattern should support lazy loading and initialization of codecs to
minimize startup time and memory footprint, enhancing the scalability of the
system. <br> **Code Suggestion**:
```
public class GrpcCompositeCodec implements HttpMessageCodec {
private final URL url;
private final FrameworkModel frameworkModel;
private final String mediaType;
private PackableMethod packableMethod;
private static final Map<MethodDescriptor, PackableMethod> cacheMap =
new ConcurrentHashMap<>();
public GrpcCompositeCodec(URL url, FrameworkModel frameworkModel,
String mediaType) {
this.url = url;
this.frameworkModel = frameworkModel;
this.mediaType = mediaType;
}
public void loadPackableMethod(MethodDescriptor methodDescriptor) {
packableMethod = cacheMap.computeIfAbsent(methodDescriptor, md ->
frameworkModel
.getExtensionLoader(PackableMethodFactory.class)
.getExtension(ConfigurationUtils.getGlobalConfiguration(url.getApplicationModel())
.getString(DUBBO_PACKABLE_METHOD_FACTORY,
DEFAULT_KEY))
.create(methodDescriptor, url, mediaType));
}
@Override
public void encode(OutputStream outputStream, Object data, Charset
charset) throws EncodeException {
...
}
@Override
public Object decode(InputStream inputStream, Class<?> targetType,
Charset charset) throws DecodeException {
...
}
...
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]