profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/tkountis/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
Thomas Kountis tkountis @apple Dublin, IE

tkountis/servicetalk 2

A networking framework that evolves with your application

tkountis/docker 0

Docker - the Linux container runtime

tkountis/hazelcast 0

Open Source In-Memory Data Grid

tkountis/hazelcast-code-samples 0

Hazelcast Code Samples

tkountis/hazelcast-diagviewer 0

Export Hazelcast Diagnostic metrics to Grafana

tkountis/hazelcast-nodejs-client 0

Hazelcast IMDG Node.js Client

tkountis/hazelcast-reference-manual 0

Hazelcast Reference Manual

tkountis/hzCmd-bench 0

bench mark implementation

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.serializer.utils;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.concurrent.api.Publisher;+import io.servicetalk.serializer.api.SerializationException;+import io.servicetalk.serializer.api.SerializerDeserializer;+import io.servicetalk.serializer.api.StreamingSerializerDeserializer;++import java.util.function.BiFunction;+import java.util.function.ToIntFunction;+import javax.annotation.Nullable;++import static java.lang.Integer.BYTES;+import static java.util.Objects.requireNonNull;+import static java.util.function.Function.identity;++/**+ * A {@link StreamingSerializerDeserializer} that uses a {@link SerializerDeserializer} and frames each object by+ * preceding it with the length in bytes. The length component is fixed and always consumes 4 bytes.+ * @param <T> The type of object to serialize.+ */+public final class FixedLengthStreamingSerializer<T> implements StreamingSerializerDeserializer<T> {

Did you consider the option to support header/footer for the streaming approach, that would help the reading side verify that the input is indeed fixed-length and validate checksum at the end. Optional of course, it can still be added later and maybe even with an additional operator.

Scottmitch

comment created time in 2 hours

PullRequestReviewEvent

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2020-2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.http.api;++import io.servicetalk.buffer.api.CharSequences;+import io.servicetalk.concurrent.api.Single;+import io.servicetalk.encoding.api.BufferDecoder;+import io.servicetalk.encoding.api.BufferDecoderGroup;+import io.servicetalk.encoding.api.BufferEncoder;++import java.util.ArrayList;+import java.util.Iterator;+import java.util.List;+import java.util.function.Function;+import javax.annotation.Nullable;++import static io.servicetalk.buffer.api.CharSequences.regionMatches;+import static io.servicetalk.concurrent.api.Single.succeeded;+import static io.servicetalk.encoding.api.Identity.identityEncoder;+import static io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw;+import static io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING;+import static io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING;+import static io.servicetalk.http.api.HttpRequestMethod.CONNECT;+import static io.servicetalk.http.api.HttpRequestMethod.HEAD;+import static io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED;+import static io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX;+import static java.util.Objects.requireNonNull;++/**+ * A {@link StreamingHttpService} that adds encoding / decoding functionality for responses and requests respectively,+ * as these are specified by the spec+ * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>.+ *+ * <p>+ * 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+        implements StreamingHttpServiceFilterFactory, HttpExecutionStrategyInfluencer {+    private final BufferDecoderGroup decompressors;+    private final List<BufferEncoder> compressors;++    /**+     * Enable support of the provided encodings for both client requests and server responses.+     * The encodings can differ for requests and responses, allowing a server that supports different compressions for+     * requests and different ones for responses.+     * <p>+     * The order of the codecs provided, affect selection priority alongside the order of the incoming+     * <a href="https://tools.ietf.org/html/rfc7231#section-5.3.4">accept-encoding</a> header from the client.+     *+     * @param decompressors used to decompress client requests if compressed.+     * @param compressors used to compress server responses if client accepts them.+     */+    public ContentEncodingHttpServiceFilter(final BufferDecoderGroup decompressors,+                                            final List<BufferEncoder> compressors) {+        this.decompressors = requireNonNull(decompressors);+        this.compressors = requireNonNull(compressors);+    }++    @Override+    public StreamingHttpServiceFilter create(final StreamingHttpService service) {+        return new StreamingHttpServiceFilter(service) {+            @Override+            public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx,+                                                        final StreamingHttpRequest request,+                                                        final StreamingHttpResponseFactory responseFactory) {+                return Single.defer(() -> {+                    final StreamingHttpRequest requestDecompressed;+                    Iterator<? extends CharSequence> contentEncodingItr =+                            request.headers().valuesIterator(CONTENT_ENCODING);+                    final boolean hasContentEncoding = contentEncodingItr.hasNext();+                    if (hasContentEncoding) {+                        BufferDecoder decoder = matchAndRemoveEncoding(decompressors.decompressors(),+                                BufferDecoder::encodingName, contentEncodingItr, request.headers());+                        if (decoder == null) {+                            return succeeded(responseFactory.unsupportedMediaType());+                        }++                        requestDecompressed = request.transformPayloadBody(pub ->+                                decoder.streamingDecoder().deserialize(pub, ctx.executionContext().bufferAllocator()));+                    } else {+                        requestDecompressed = request;+                    }++                    return super.handle(ctx, requestDecompressed, responseFactory).map(response -> {+                        final CharSequence reqAcceptEncoding;+                        if (isPassThrough(request.method(), response) ||+                                (reqAcceptEncoding = request.headers().get(ACCEPT_ENCODING)) == null) {+                            return response;+                        }++                        BufferEncoder encoder = negotiateAcceptedEncodingRaw(reqAcceptEncoding, compressors,+                                BufferEncoder::encodingName);+                        if (encoder == null || identityEncoder().equals(encoder)) {+                            return response;+                        }++                        HeaderUtils.addContentEncoding(response.headers(), encoder.encodingName());

nit: static import

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.data.jackson;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.concurrent.PublisherSource.Subscriber;+import io.servicetalk.concurrent.PublisherSource.Subscription;+import io.servicetalk.concurrent.api.Publisher;+import io.servicetalk.concurrent.api.PublisherOperator;+import io.servicetalk.concurrent.internal.ConcurrentSubscription;+import io.servicetalk.serializer.api.SerializationException;+import io.servicetalk.serializer.api.StreamingSerializerDeserializer;++import com.fasterxml.jackson.core.JsonParser;+import com.fasterxml.jackson.core.JsonToken;+import com.fasterxml.jackson.core.async.ByteArrayFeeder;+import com.fasterxml.jackson.core.async.ByteBufferFeeder;+import com.fasterxml.jackson.core.async.NonBlockingInputFeeder;+import com.fasterxml.jackson.core.type.TypeReference;+import com.fasterxml.jackson.databind.JavaType;+import com.fasterxml.jackson.databind.JsonNode;+import com.fasterxml.jackson.databind.ObjectMapper;+import com.fasterxml.jackson.databind.ObjectReader;+import com.fasterxml.jackson.databind.ObjectWriter;+import com.fasterxml.jackson.databind.node.ArrayNode;+import com.fasterxml.jackson.databind.node.BooleanNode;+import com.fasterxml.jackson.databind.node.NullNode;+import com.fasterxml.jackson.databind.node.ObjectNode;+import com.fasterxml.jackson.databind.node.TextNode;++import java.io.IOException;+import java.util.ArrayDeque;+import java.util.ArrayList;+import java.util.Deque;+import java.util.List;+import javax.annotation.Nullable;++import static com.fasterxml.jackson.databind.node.JsonNodeFactory.instance;+import static io.servicetalk.concurrent.internal.EmptySubscriptions.EMPTY_SUBSCRIPTION;+import static io.servicetalk.data.jackson.JacksonSerializer.doSerialize;+import static java.util.Collections.singletonList;+import static java.util.function.Function.identity;++/**+ * Serialize a stream of JSON objects.+ * @param <T> The type of objects to serialize.+ */+final class JacksonStreamingSerializer<T> implements StreamingSerializerDeserializer<T> {+    private final ObjectWriter writer;+    private final ObjectReader reader;++    JacksonStreamingSerializer(ObjectMapper mapper, Class<T> clazz) {+        writer = mapper.writerFor(clazz);+        reader = mapper.readerFor(clazz);+    }++    JacksonStreamingSerializer(ObjectMapper mapper, TypeReference<T> typeRef) {+        writer = mapper.writerFor(typeRef);+        reader = mapper.readerFor(typeRef);+    }++    JacksonStreamingSerializer(ObjectMapper mapper, JavaType type) {+        writer = mapper.writerFor(type);+        reader = mapper.readerFor(type);+    }++    @Override+    public Publisher<Buffer> serialize(final Publisher<T> toSerialize, final BufferAllocator allocator) {+        return toSerialize.map(t -> {+            Buffer buffer = allocator.newBuffer();+            doSerialize(writer, t, buffer);+            return buffer;+        });+    }++    @Override+    public Publisher<T> deserialize(final Publisher<Buffer> serializedData, final BufferAllocator allocator) {+        return serializedData.liftSync(new DeserializeOperator<T>(reader)).flatMapConcatIterable(identity());+    }++    private static final class DeserializeOperator<T> implements PublisherOperator<Buffer, Iterable<T>> {+        private final ObjectReader reader;++        private DeserializeOperator(ObjectReader reader) {+            this.reader = reader;+        }++        @Override+        public Subscriber<? super Buffer> apply(final Subscriber<? super Iterable<T>> subscriber) {+            final JsonParser parser;+            try {+                // TODO(scott): ByteBufferFeeder is currently not supported by jackson, and the current API throws

Do we want this in now? Shall we open a radar?

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.serializer.utils;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.concurrent.api.Publisher;+import io.servicetalk.serializer.api.SerializationException;+import io.servicetalk.serializer.api.SerializerDeserializer;+import io.servicetalk.serializer.api.StreamingSerializerDeserializer;++import java.util.function.BiFunction;+import java.util.function.ToIntFunction;+import javax.annotation.Nullable;++import static java.util.Objects.requireNonNull;+import static java.util.function.Function.identity;++/**+ * A {@link StreamingSerializerDeserializer} that uses a {@link SerializerDeserializer} and frames each object by+ * preceding it with the length in bytes. The length component is variable length an encoded as

"variable length an encoded as" -> "variable length and encoded as"

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.serializer.api;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;++/**+ * Serialize from {@link Object} to {@link Buffer} and deserialize objects from {@link Buffer} to {@link Object}.

javadoc out of sync

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.serializer.utils;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.serializer.api.SerializerDeserializer;++import java.nio.charset.Charset;+import java.util.Collection;+import java.util.HashMap;+import java.util.Map;++import static io.servicetalk.utils.internal.CharsetUtils.standardCharsets;++abstract class AbstractStringSerializer implements SerializerDeserializer<String> {

Serializer/Deserializer in name? same for subclass

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2020-2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.http.api;++import io.servicetalk.buffer.api.CharSequences;+import io.servicetalk.concurrent.api.Single;+import io.servicetalk.encoding.api.BufferDecoder;+import io.servicetalk.encoding.api.BufferDecoderGroup;+import io.servicetalk.encoding.api.BufferEncoder;++import java.util.ArrayList;+import java.util.Iterator;+import java.util.List;+import java.util.function.Function;+import javax.annotation.Nullable;++import static io.servicetalk.buffer.api.CharSequences.regionMatches;+import static io.servicetalk.concurrent.api.Single.succeeded;+import static io.servicetalk.encoding.api.Identity.identityEncoder;+import static io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw;+import static io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING;+import static io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING;+import static io.servicetalk.http.api.HttpRequestMethod.CONNECT;+import static io.servicetalk.http.api.HttpRequestMethod.HEAD;+import static io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED;+import static io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX;+import static java.util.Objects.requireNonNull;++/**+ * A {@link StreamingHttpService} that adds encoding / decoding functionality for responses and requests respectively,+ * as these are specified by the spec+ * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>.+ *+ * <p>+ * 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+        implements StreamingHttpServiceFilterFactory, HttpExecutionStrategyInfluencer {+    private final BufferDecoderGroup decompressors;+    private final List<BufferEncoder> compressors;++    /**+     * Enable support of the provided encodings for both client requests and server responses.+     * The encodings can differ for requests and responses, allowing a server that supports different compressions for+     * requests and different ones for responses.+     * <p>+     * The order of the codecs provided, affect selection priority alongside the order of the incoming+     * <a href="https://tools.ietf.org/html/rfc7231#section-5.3.4">accept-encoding</a> header from the client.+     *+     * @param decompressors used to decompress client requests if compressed.+     * @param compressors used to compress server responses if client accepts them.+     */+    public ContentEncodingHttpServiceFilter(final BufferDecoderGroup decompressors,+                                            final List<BufferEncoder> compressors) {+        this.decompressors = requireNonNull(decompressors);+        this.compressors = requireNonNull(compressors);+    }++    @Override+    public StreamingHttpServiceFilter create(final StreamingHttpService service) {+        return new StreamingHttpServiceFilter(service) {+            @Override+            public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx,+                                                        final StreamingHttpRequest request,+                                                        final StreamingHttpResponseFactory responseFactory) {+                return Single.defer(() -> {+                    final StreamingHttpRequest requestDecompressed;+                    Iterator<? extends CharSequence> contentEncodingItr =+                            request.headers().valuesIterator(CONTENT_ENCODING);+                    final boolean hasContentEncoding = contentEncodingItr.hasNext();+                    if (hasContentEncoding) {+                        BufferDecoder decoder = matchAndRemoveEncoding(decompressors.decompressors(),+                                BufferDecoder::encodingName, contentEncodingItr, request.headers());+                        if (decoder == null) {+                            return succeeded(responseFactory.unsupportedMediaType());+                        }++                        requestDecompressed = request.transformPayloadBody(pub ->+                                decoder.streamingDecoder().deserialize(pub, ctx.executionContext().bufferAllocator()));+                    } else {+                        requestDecompressed = request;+                    }++                    return super.handle(ctx, requestDecompressed, responseFactory).map(response -> {+                        final CharSequence reqAcceptEncoding;+                        if (isPassThrough(request.method(), response) ||+                                (reqAcceptEncoding = request.headers().get(ACCEPT_ENCODING)) == null) {+                            return response;+                        }++                        BufferEncoder encoder = negotiateAcceptedEncodingRaw(reqAcceptEncoding, compressors,+                                BufferEncoder::encodingName);+                        if (encoder == null || identityEncoder().equals(encoder)) {+                            return response;+                        }++                        HeaderUtils.addContentEncoding(response.headers(), encoder.encodingName());+                        return response.transformPayloadBody(bufPub ->+                                encoder.streamingEncoder().serialize(bufPub, ctx.executionContext().bufferAllocator()));+                    }).subscribeShareContext();+                });+            }+        };+    }++    @Override+    public HttpExecutionStrategy influenceStrategy(final HttpExecutionStrategy strategy) {+        // No influence - no blocking+        return strategy;+    }++    private static boolean isPassThrough(final HttpRequestMethod method, final StreamingHttpResponse response) {+        // see. https://tools.ietf.org/html/rfc7230#section-3.3.3+        // The length of a message body is determined by one of the following+        //         (in order of precedence):+        //+        // 1.  Any response to a HEAD request and any response with a 1xx+        //         (Informational), 204 (No Content), or 304 (Not Modified) status+        // code is always terminated by the first empty line after the+        // header fields, regardless of the header fields present in the+        // message, and thus cannot contain a message body.+        //+        // 2.  Any 2xx (Successful) response to a CONNECT request implies that+        // the connection will become a tunnel immediately after the empty+        // line that concludes the header fields.  A client MUST ignore any+        // Content-Length or Transfer-Encoding header fields received in+        // such a message.+        // ...+        final int code = response.status().code();+        return INFORMATIONAL_1XX.contains(code) || code == NO_CONTENT.code() || code == NOT_MODIFIED.code() ||+                (method == HEAD || (method == CONNECT && SUCCESSFUL_2XX.contains(code)));+    }++    @Nullable+    static <T> T matchAndRemoveEncoding(final List<T> supportedEncoders,

anyway we can extract parts of this to remove duplication between this and HeaderUtils#negotiateAcceptedEncodingRaw

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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.+ */++apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library"++dependencies {+  api project(":servicetalk-buffer-api")+  api project(":servicetalk-concurrent-api")+  api project(":servicetalk-oio-api")++  implementation project(":servicetalk-annotations")+  implementation project(":servicetalk-concurrent-api-internal")+  implementation project(":servicetalk-oio-api-internal")+  implementation "com.google.code.findbugs:jsr305:$jsr305Version"++  testImplementation testFixtures(project(":servicetalk-concurrent-api"))+  testImplementation testFixtures(project(":servicetalk-concurrent-internal"))+  testImplementation project(":servicetalk-concurrent-test-internal")+  testImplementation "junit:junit:$junitVersion"

are they needed? no tests

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.data.jackson;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.serializer.api.SerializationException;+import io.servicetalk.serializer.api.SerializerDeserializer;++import com.fasterxml.jackson.core.type.TypeReference;+import com.fasterxml.jackson.databind.JavaType;+import com.fasterxml.jackson.databind.ObjectMapper;+import com.fasterxml.jackson.databind.ObjectReader;+import com.fasterxml.jackson.databind.ObjectWriter;++import java.io.IOException;++import static io.servicetalk.buffer.api.Buffer.asOutputStream;++/**+ * Serializes and deserializes to/from JSON via jackson.+ * @param <T> The type of objects to serialize.+ */+final class JacksonSerializer<T> implements SerializerDeserializer<T> {

Consider Serialiazer/Deserializer in name

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.data.jackson;++import io.servicetalk.buffer.api.Buffer;+import io.servicetalk.buffer.api.BufferAllocator;+import io.servicetalk.concurrent.PublisherSource.Subscriber;+import io.servicetalk.concurrent.PublisherSource.Subscription;+import io.servicetalk.concurrent.api.Publisher;+import io.servicetalk.concurrent.api.PublisherOperator;+import io.servicetalk.concurrent.internal.ConcurrentSubscription;+import io.servicetalk.serializer.api.SerializationException;+import io.servicetalk.serializer.api.StreamingSerializerDeserializer;++import com.fasterxml.jackson.core.JsonParser;+import com.fasterxml.jackson.core.JsonToken;+import com.fasterxml.jackson.core.async.ByteArrayFeeder;+import com.fasterxml.jackson.core.async.ByteBufferFeeder;+import com.fasterxml.jackson.core.async.NonBlockingInputFeeder;+import com.fasterxml.jackson.core.type.TypeReference;+import com.fasterxml.jackson.databind.JavaType;+import com.fasterxml.jackson.databind.JsonNode;+import com.fasterxml.jackson.databind.ObjectMapper;+import com.fasterxml.jackson.databind.ObjectReader;+import com.fasterxml.jackson.databind.ObjectWriter;+import com.fasterxml.jackson.databind.node.ArrayNode;+import com.fasterxml.jackson.databind.node.BooleanNode;+import com.fasterxml.jackson.databind.node.NullNode;+import com.fasterxml.jackson.databind.node.ObjectNode;+import com.fasterxml.jackson.databind.node.TextNode;++import java.io.IOException;+import java.util.ArrayDeque;+import java.util.ArrayList;+import java.util.Deque;+import java.util.List;+import javax.annotation.Nullable;++import static com.fasterxml.jackson.databind.node.JsonNodeFactory.instance;+import static io.servicetalk.concurrent.internal.EmptySubscriptions.EMPTY_SUBSCRIPTION;+import static io.servicetalk.data.jackson.JacksonSerializer.doSerialize;+import static java.util.Collections.singletonList;+import static java.util.function.Function.identity;++/**+ * Serialize a stream of JSON objects.

Serialize and deserialize

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2020-2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.http.api;++import io.servicetalk.buffer.api.CharSequences;+import io.servicetalk.concurrent.api.Single;+import io.servicetalk.encoding.api.BufferDecoder;+import io.servicetalk.encoding.api.BufferDecoderGroup;+import io.servicetalk.encoding.api.BufferEncoder;++import java.util.ArrayList;+import java.util.Iterator;+import java.util.List;+import java.util.function.Function;+import javax.annotation.Nullable;++import static io.servicetalk.buffer.api.CharSequences.regionMatches;+import static io.servicetalk.concurrent.api.Single.succeeded;+import static io.servicetalk.encoding.api.Identity.identityEncoder;+import static io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw;+import static io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING;+import static io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING;+import static io.servicetalk.http.api.HttpRequestMethod.CONNECT;+import static io.servicetalk.http.api.HttpRequestMethod.HEAD;+import static io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED;+import static io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX;+import static java.util.Objects.requireNonNull;++/**+ * A {@link StreamingHttpService} that adds encoding / decoding functionality for responses and requests respectively,+ * as these are specified by the spec+ * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>.+ *+ * <p>+ * 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+        implements StreamingHttpServiceFilterFactory, HttpExecutionStrategyInfluencer {+    private final BufferDecoderGroup decompressors;+    private final List<BufferEncoder> compressors;++    /**+     * Enable support of the provided encodings for both client requests and server responses.+     * The encodings can differ for requests and responses, allowing a server that supports different compressions for+     * requests and different ones for responses.+     * <p>+     * The order of the codecs provided, affect selection priority alongside the order of the incoming+     * <a href="https://tools.ietf.org/html/rfc7231#section-5.3.4">accept-encoding</a> header from the client.+     *+     * @param decompressors used to decompress client requests if compressed.+     * @param compressors used to compress server responses if client accepts them.+     */+    public ContentEncodingHttpServiceFilter(final BufferDecoderGroup decompressors,

It's not common practise for requests to be compressed, I think a single constructor makes sense to support it.

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

 default boolean hasQueryParameter(final String key) {     @Nullable     HostAndPort effectiveHostAndPort(); +    /**+     * Get the {@link BufferEncoder} to use for this request.+     * @return the {@link BufferEncoder} to use for this request.+     */+    @Nullable+    BufferEncoder requestEncoder();++    /**+     * Set the {@link BufferEncoder} to use for this request.+     * @param encoder {@link BufferEncoder} to use for this request.+     * @return {@code this}.

Consider adding a link to the relevant rfc section <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>

Scottmitch

comment created time in 5 days

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2020-2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.http.api;++import io.servicetalk.buffer.api.CharSequences;+import io.servicetalk.concurrent.api.Single;+import io.servicetalk.encoding.api.BufferDecoder;+import io.servicetalk.encoding.api.BufferDecoderGroup;+import io.servicetalk.encoding.api.BufferEncoder;++import java.util.ArrayList;+import java.util.Iterator;+import java.util.List;+import java.util.function.Function;+import javax.annotation.Nullable;++import static io.servicetalk.buffer.api.CharSequences.regionMatches;+import static io.servicetalk.concurrent.api.Single.succeeded;+import static io.servicetalk.encoding.api.Identity.identityEncoder;+import static io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw;+import static io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING;+import static io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING;+import static io.servicetalk.http.api.HttpRequestMethod.CONNECT;+import static io.servicetalk.http.api.HttpRequestMethod.HEAD;+import static io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED;+import static io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX;+import static java.util.Objects.requireNonNull;++/**+ * A {@link StreamingHttpService} that adds encoding / decoding functionality for responses and requests respectively,+ * as these are specified by the spec+ * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>.+ *+ * <p>+ * 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+        implements StreamingHttpServiceFilterFactory, HttpExecutionStrategyInfluencer {+    private final BufferDecoderGroup decompressors;+    private final List<BufferEncoder> compressors;++    /**+     * Enable support of the provided encodings for both client requests and server responses.

The doc is out of sync with the new API

Scottmitch

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentapple/servicetalk

New Serializer APIs, consolidation of ContentCodec, and gRPC MethodDescriptor

+/*+ * Copyright © 2020-2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.http.api;++import io.servicetalk.buffer.api.CharSequences;+import io.servicetalk.concurrent.api.Single;+import io.servicetalk.encoding.api.BufferDecoder;+import io.servicetalk.encoding.api.BufferDecoderGroup;+import io.servicetalk.encoding.api.BufferEncoder;++import java.util.ArrayList;+import java.util.Iterator;+import java.util.List;+import java.util.function.Function;+import javax.annotation.Nullable;++import static io.servicetalk.buffer.api.CharSequences.regionMatches;+import static io.servicetalk.concurrent.api.Single.succeeded;+import static io.servicetalk.encoding.api.Identity.identityEncoder;+import static io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw;+import static io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING;+import static io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING;+import static io.servicetalk.http.api.HttpRequestMethod.CONNECT;+import static io.servicetalk.http.api.HttpRequestMethod.HEAD;+import static io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED;+import static io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX;+import static io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX;+import static java.util.Objects.requireNonNull;++/**+ * A {@link StreamingHttpService} that adds encoding / decoding functionality for responses and requests respectively,+ * as these are specified by the spec+ * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.2.2">Content-Encoding</a>.+ *+ * <p>+ * 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

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).

Scottmitch

comment created time in 5 days

PullRequestReviewEvent

push eventapple/servicetalk

Thomas Kountis

commit sha 1a2aa0599c3d29aa963bdb99db182ee760a0a036

Relax OpenTracing HttpHeaders formatter to allow custom containers (#1703) Motivation: Currently the HttpHeaders formatter is non-public API and strongly typed around our own HttpHeaders interface. Users who want to use our OpenTracing API and utilize a formatter with their own carrier they end up duplicating the same code. Modifications: Deprecated current solution, and introduced a KeyValue formatter that allows a custom injector and extractor. Result: Additional API exposed for OpenTracing users.

view details

push time in 6 days

PR merged apple/servicetalk

Relax OpenTracing HttpHeaders formatter to allow custom containers

Motivation:

Currently the HttpHeaders formatter is non-public API and strongly typed around our own HttpHeaders interface. Users who want to use our OpenTracing API and utilize a formatter with their own carrier they end up duplicating the same code.

Modifications:

Deprecated current solution, and introduced a KeyValue formatter that allows a custom injector and extractor.

Result:

Additional API exposed for OpenTracing users.

+128 -28

1 comment

6 changed files

tkountis

pr closed time in 6 days

push eventtkountis/servicetalk

Thomas Kountis

commit sha 8ac2d90f0896525a1ac7e5b2d35b747cd3d28893

Comments

view details

push time in 6 days

PullRequestReviewEvent

Pull request review commentapple/servicetalk

Relax OpenTracing HttpHeaders formatter to allow custom containers

 apply plugin: "io.servicetalk.servicetalk-gradle-plugin-internal-library"  dependencies {   api project(":servicetalk-opentracing-inmemory-api")+  api project(":servicetalk-concurrent")

I missed them 🤦

tkountis

comment created time in 6 days

push eventtkountis/servicetalk

Thomas Kountis

commit sha 88c30f4efe4c94215e625dc417e476bf11a55023

Comments

view details

push time in 6 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentapple/servicetalk

Add examples for redirect handling

 Using the following classes: NOTE: This example uses the link:#blocking-aggregated[blocking + aggregated] API, as the TLS/SSL configuration API is the same across all the HTTP APIs. +[#Redirects]+== Redirects++Extends the async "Hello World" example to demonstrate different ways how users can support redirects in ServiceTalk

"ways how" -> "ways that"

idelpivnitskiy

comment created time in 6 days

push eventtkountis/servicetalk

Thomas Kountis

commit sha 3ed0f34aead4169811826d1be2b68159409b1423

Comments

view details

push time in 6 days

Pull request review commentapple/servicetalk

Relax OpenTracing formatter for HttpHeaders to allow custom containers

+/*+ * Copyright © 2021 Apple Inc. and the ServiceTalk project 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 io.servicetalk.opentracing.inmemory;++import javax.annotation.Nullable;++/**+ * An Key Value accessor interface that works with {@link CharSequence} types.+ */+public interface CharSequenceKeyValueAccessor {

The classes are now gone. They B3KeyValue formatter allows for generic injector/extractors to be passed in.

tkountis

comment created time in 6 days