-
Notifications
You must be signed in to change notification settings - Fork 183
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
New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor #1673
Conversation
test failure attributed to #1579 |
a3dcaab
to
79481dc
Compare
build failure attributed to #1663 |
a31c3a5
to
313c05d
Compare
build failure attributed to #1663 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
70/304 files so far…
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpHeaderValues.java
Outdated
Show resolved
Hide resolved
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpDeserializer2.java
Show resolved
Hide resolved
...izer-utils/src/main/java/io/servicetalk/serializer/utils/FixedLengthStreamingSerializer.java
Outdated
Show resolved
Hide resolved
...izer-utils/src/main/java/io/servicetalk/serializer/utils/FixedLengthStreamingSerializer.java
Outdated
Show resolved
Hide resolved
...cetalk-serializer-api/src/main/java/io/servicetalk/serializer/api/StreamingDeserializer.java
Show resolved
Hide resolved
...-serializer-utils/src/main/java/io/servicetalk/serializer/utils/StringCharsetSerializer.java
Outdated
Show resolved
Hide resolved
...-serializer-utils/src/main/java/io/servicetalk/serializer/utils/StringCharsetSerializer.java
Outdated
Show resolved
Hide resolved
...alk-serializer-utils/src/main/java/io/servicetalk/serializer/utils/StringUtf8Serializer.java
Outdated
Show resolved
Hide resolved
52cfb1f
to
f20e3c6
Compare
another #1579 |
another #1663 |
1 similar comment
another #1663 |
6dfba1d
to
1b4c5e9
Compare
a164ae6
to
b623507
Compare
build failure attributed to #1579 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
approve for examples portion
@@ -26,8 +26,7 @@ | |||
import java.util.function.BooleanSupplier; | |||
|
|||
import static io.servicetalk.concurrent.api.Single.succeeded; | |||
import static io.servicetalk.http.api.HttpSerializationProviders.textDeserializer; | |||
import static io.servicetalk.http.api.HttpSerializationProviders.textSerializer; | |||
import static io.servicetalk.http.api.HttpSerializers.textSerializerUtf8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems odd to see textSerializerUtf8 in sites that are deserialization. Perhaps naming it textSerializationUtf8
would be less suggestive that the usage is serializing rather than deserializing.
.../java/io/servicetalk/examples/http/helloworld/async/streaming/HelloWorldStreamingClient.java
Outdated
Show resolved
Hide resolved
.../serialization/src/main/java/io/servicetalk/examples/http/serialization/SerializerUtils.java
Outdated
Show resolved
Hide resolved
* Append this filter before others that are expected to to see compressed content for this request/response, and after | ||
* other filters that expect to see/manipulate the original payload. | ||
*/ | ||
public final class ContentEncodingHttpServiceFilter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Coding as noun has both the meaning of encoding or decoding. I think the name before made more sense. The comment is worth considering across the whole encoding/decoding APIs (didn't want to duplicate it).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
related/duplicate of #1673 (comment) ... lets discuss there if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1st round.
General comments:
- that I didn't want to repeat, it's probably worth sticking to ser/deser naming convention to all implementations.
- new APIs are certainly better and I love the effort with varint streaming support.
...icetalk-http-api/src/main/java/io/servicetalk/http/api/ContentEncodingHttpServiceFilter.java
Outdated
Show resolved
Hide resolved
...icetalk-http-api/src/main/java/io/servicetalk/http/api/ContentEncodingHttpServiceFilter.java
Outdated
Show resolved
Hide resolved
...icetalk-http-api/src/main/java/io/servicetalk/http/api/ContentEncodingHttpServiceFilter.java
Outdated
Show resolved
Hide resolved
} | ||
|
||
@Nullable | ||
static <T> T matchAndRemoveEncoding(final List<T> supportedEncoders, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
anyway we can extract parts of this to remove duplication between this and HeaderUtils#negotiateAcceptedEncodingRaw
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried sharing code between these two methods but they are doing different jobs and I couldn't find a good way. I considered at least moving them into the same HeaderUtils
file, to keep similar code close but the matchAndRemoveEncoding
can be kept package private if it stays here.
matchAndRemoveEncoding
-> needs to remove the encoding header that is matched at preserve ordering (bcz the body has been decoded and the header no longer applies). first header must supported values or else we can't decode and its an error.
negotiateAcceptedEncodingRaw
-> finds a matching encoding, so it can be applied (no removal of headers). any match is acceptable.
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpRequestMetaData.java
Show resolved
Hide resolved
|
||
import static io.servicetalk.utils.internal.CharsetUtils.standardCharsets; | ||
|
||
abstract class AbstractStringSerializer implements SerializerDeserializer<String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serializer/Deserializer in name? same for subclass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A shorthand in the form of SerDe is frequently used in the community.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The strategy I used was to be explicit with the interface names (SerializerDeserializer
, BufferEncoderDecoder
) but just use the "serializer" variant for concrete method/type names that fill both roles for brevity (StringSerializer
, NettyBufferEncoders#bufferEncoder(..)
, HttpSerializers#textSerializerUtf8()
). In practice I'm not sure lengthening the names of concrete types/methods, or using abbreviations (SerDe
), will improve understandability/readability.
...zer-utils/src/main/java/io/servicetalk/serializer/utils/VarIntLengthStreamingSerializer.java
Outdated
Show resolved
Hide resolved
* Serializes and deserializes to/from JSON via jackson. | ||
* @param <T> The type of objects to serialize. | ||
*/ | ||
final class JacksonSerializer<T> implements SerializerDeserializer<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider Serialiazer/Deserializer in name
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
duplicate of #1673 (comment) ... lets discuss there if necessary.
...etalk-data-jackson/src/main/java/io/servicetalk/data/jackson/JacksonStreamingSerializer.java
Outdated
Show resolved
Hide resolved
...etalk-data-jackson/src/main/java/io/servicetalk/data/jackson/JacksonStreamingSerializer.java
Show resolved
Hide resolved
}; | ||
} | ||
|
||
private static final class BlockingStreamingHttpMessageBodyAdapter<I> implements BlockingIterator<Buffer> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should access to this class' state be made thread-safe? BlockingIterator
comes from the io.servicetalk.concurrent
package. I'd assume it can be used in a concurrent context. The parent class has no mention of it requiring single-thread access.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No this isn't necessary. BlockingIterator
is in concurrent
package because it is how we convert to/from java.util.Iterator
related types. This type just adds timeouts at the call site and makes iterable Closable
(which will cancel the underlying publisher if it isn't fully consumed).
build failure attributed to #1579 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will submit my review in chunks:
...alk-serializer-api/src/main/java/io/servicetalk/serializer/api/StreamingSerializerUtils.java
Outdated
Show resolved
Hide resolved
...serialization-api/src/main/java/io/servicetalk/serialization/api/SerializationException.java
Outdated
Show resolved
Hide resolved
...talk-serializer-utils/src/main/java/io/servicetalk/serializer/utils/ByteArraySerializer.java
Outdated
Show resolved
Hide resolved
...izer-utils/src/main/java/io/servicetalk/serializer/utils/FixedLengthStreamingSerializer.java
Show resolved
Hide resolved
...serializer-utils/src/main/java/io/servicetalk/serializer/utils/AbstractStringSerializer.java
Show resolved
Hide resolved
...cetalk-encoding-api/src/main/java/io/servicetalk/encoding/api/BufferDecoderGroupBuilder.java
Show resolved
Hide resolved
servicetalk-encoding-api/src/main/java/io/servicetalk/encoding/api/BufferEncodingException.java
Outdated
Show resolved
Hide resolved
servicetalk-encoding-api/src/main/java/io/servicetalk/encoding/api/CodecDecodingException.java
Outdated
Show resolved
Hide resolved
...alk-encoding-api/src/main/java/io/servicetalk/encoding/api/IdentityBufferEncoderDecoder.java
Show resolved
Hide resolved
...-encoding-netty/src/main/java/io/servicetalk/encoding/netty/DefaultBufferEncoderDecoder.java
Show resolved
Hide resolved
build failure attributed to #1579 |
another #1579 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far the approach looks good! Lots of improvements.
I still need to look at grpc. Everything else is reviewed. But don't be blocked by that.
servicetalk-data-jackson/src/main/java/io/servicetalk/data/jackson/JacksonSerializerCache.java
Outdated
Show resolved
Hide resolved
...data-jackson/src/test/java/io/servicetalk/data/jackson/JacksonSerializationProviderTest.java
Show resolved
Hide resolved
...src/main/java/io/servicetalk/data/jackson/jersey/SerializationExceptionMapperDeprecated.java
Outdated
Show resolved
Hide resolved
servicetalk-data-jackson/src/main/java/io/servicetalk/data/jackson/JacksonSerializerCache.java
Outdated
Show resolved
Hide resolved
servicetalk-data-protobuf/src/main/java/io/servicetalk/data/protobuf/ProtobufSerializer.java
Outdated
Show resolved
Hide resolved
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HeaderUtils.java
Show resolved
Hide resolved
...tp-api/src/main/java/io/servicetalk/http/api/DefaultHttpStreamingSerializerDeserializer.java
Show resolved
Hide resolved
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpSerializers.java
Show resolved
Hide resolved
servicetalk-http-api/src/main/java/io/servicetalk/http/api/HttpSerializers.java
Show resolved
Hide resolved
servicetalk-http-api/src/main/java/io/servicetalk/http/api/StreamingHttpPayloadHolder.java
Outdated
Show resolved
Hide resolved
…scriptor Motivation: Supporting a custom transport for gRPC currently requires reflection and special knowledge of types for serialization. The generated code has information related to types and serialization that can be exposed to the runtime which also allows supporting custom transports. This task requires exposing serializer APIs into the public API. Our existing serializer APIs were heavily influced by streaming use cases and JSON serialization which can serialize any type and generally doesn't have type restrictions. This lead to a general SerializationProvider API which is impossible to constrain types due to the generics being at the method level, which doesn't account for implementing serialization for type constrained approached (protobuf MessageLite). Also the serialization APIs couple scalar and streaming use cases which in practice are more commonly decoupled into scalar (individual objects) and streaming (which applies some framing around individual objects). These concepts are coupled which leads to confusing specializations (deserializeAggregatedSingle, deserializeAggregated) which are easy to misuse and lead to invalid serialization in practice (streaming {form url, string} encoding are not properly framed and may not be deserialized correctly). The existing Serializer APIs also do not promote composability in that if you can serialize one object you should be able to re-use that serialization for a stream of objects with some frameing applied on top (required for gRPC). Modifications: - Introduce a new servicetalk-serializer-api package with new Serializer APIs. - Introduce a new servicetalk-serializer-utils package with common utilities for serialization such as streaming framing (fixed and varint length prefixed) - Introduce BufferEncoder APIs in servicetalk-encoding-api for compression and decompression. This also comes with NettyBufferEncoders and NettyCompression to create Netty backed implementations. - Introduce HttpStreamingSerializer and new HttpSerializer APIs in servicetalk-http-api, and modify all request/response APIs to use the new serializer APIs. Introduce new methods to deserialize and process trailers. - Introduce HttpSerializers in servicetalk-http-api for implementations of the new APIs. - Introduce JacksonSerializerCache in servicetalk-http-api as the new entry point to create/cache serializers for JSON. - Introduce ProtobufSerializerCache in servicetalk-data-protobuf as the new entry point to create/cache serializers for protobuf. - Introduce MethodDescriptor API into servicetalk-grpc-api and update code generation to use this new API. - Update all examples avoid usage of deprecated APIs and leverage new APIs. - Deprecate the following APIs and related methods in favor of the new types descrbied above: - SerializationProvider, JacksonSerializationProvider, ProtobufSerializationProvider, GrpcSerializationProvider, HttpSerializationProvider - ContentCodec, CodecDecodingException, CodecEncodingException, ContentCodings - GrpcMetadata#path(), code generated types that extend DefaultGrpcClientMetadata Result: gRPC API supports MethodDescriptor, which uses new Serializer APIs, and the entire code base has been updated to use the new APIs consistently. make control flow in ConnectionCloseHeaderHandlingTest and GracefulConnectionClosureHandlingTest more robust
9d8543d
to
b6761a7
Compare
* Get the {@link HttpMessageBodyIterable} for this request. | ||
* @return the {@link HttpMessageBodyIterable} for this request. | ||
*/ | ||
HttpMessageBodyIterable<Buffer> messageBody(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
continuation of #1673 (comment)
@idelpivnitskiy @chemicL - note that I removed BlockingStreamingHttpMessageBody
originally introduced in this PR in favor of HttpMessageBodyIterable
(happy to discuss/iterate). The motivation is the functional APIs such as TrailersTransformer doesn't lend themselves to the sequential programming style of traditional blocking APIs. I meant to deprecate the transform methods on the blocking request/response APIs but forgot (will push this change). The BlockingIterable
types are still cumbersome to create but I think that can be improved over time (more utilities) and also we have a task to investigate removal of BlockingIterable
(in favor of ClosableIterable
).
build failure attributed to #1294 |
build failure attributed to #1507 |
Motivation:
Supporting a custom transport for gRPC currently requires
reflection and special knowledge of types for serialization. The
generated code has information related to types and serialization that
can be exposed to the runtime which also allows supporting custom
transports.
This task requires exposing serializer APIs into the public
API. Our existing serializer APIs were heavily influced by streaming use
cases and JSON serialization which can serialize any type and generally
doesn't have type restrictions. This lead to a general
SerializationProvider API which is impossible to constrain types due to
the generics being at the method level, which doesn't account for
implementing serialization for type constrained approached (protobuf
MessageLite). Also the serialization APIs couple scalar and streaming
use cases which in practice are more commonly decoupled into scalar
(individual objects) and streaming (which applies some framing around
individual objects). These concepts are coupled which leads to confusing
specializations (deserializeAggregatedSingle, deserializeAggregated)
which are easy to misuse and lead to invalid serialization in practice
(streaming {form url, string} encoding are not properly framed and may
not be deserialized correctly). The existing Serializer APIs also do not
promote composability in that if you can serialize one object you should
be able to re-use that serialization for a stream of objects with some
frameing applied on top (required for gRPC).
Modifications:
Serializer APIs.
utilities for serialization such as streaming framing (fixed and
varint length prefixed)
compression and decompression. This also comes with
NettyBufferEncoders and NettyCompression to create Netty backed
implementations.
servicetalk-http-api, and modify all request/response APIs to use the
new serializer APIs. Introduce new methods to deserialize and process
trailers.
of the new APIs.
entry point to create/cache serializers for JSON.
new entry point to create/cache serializers for protobuf.
code generation to use this new API.
APIs.
types descrbied above:
ProtobufSerializationProvider, GrpcSerializationProvider,
HttpSerializationProvider
ContentCodings
DefaultGrpcClientMetadata
Result:
gRPC API supports MethodDescriptor, which uses new Serializer APIs, and
the entire code base has been updated to use the new APIs consistently.