Skip to content

Commit

Permalink
Deprecate append method on all filter factories (#1578)
Browse files Browse the repository at this point in the history
Motivation:

All `*FilterFactory` interfaces currently implement default `append`
method that helps to chain filters in order of append. Because
internally it uses wrapping approach, it can hide
`HttpExecutionStrategyInfluencer` implementation of the passed filter
factory. To avoid that, users have to use a method on the client/server
builder instead.

Modifications:

- Deprecate `append` method on all filter factories;
- Add `FilterFactoryUtils` test fixture as the replacement utility for
tests;

Result:

Users won't hide `HttpExecutionStrategyInfluencer` impl when they chain
filters.
  • Loading branch information
idelpivnitskiy authored May 26, 2021
1 parent ce49400 commit 6f0d87f
Show file tree
Hide file tree
Showing 20 changed files with 233 additions and 95 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018, 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.
Expand Down Expand Up @@ -48,9 +48,12 @@ public interface ConnectionFactoryFilter<ResolvedAddress, C extends ListenableAs
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; original connection factory
* </pre>
*
* @deprecated Use {@code appendConnectionFactoryFilter(ConnectionFactoryFilter)} at the builder of a client
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before} function and then applies this function.
*/
@Deprecated
default ConnectionFactoryFilter<ResolvedAddress, C> append(ConnectionFactoryFilter<ResolvedAddress, C> before) {
requireNonNull(before);
return original -> create(before.create(original));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018, 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.
Expand Down Expand Up @@ -252,10 +252,17 @@ DefaultDnsServiceDiscovererBuilder srvFilterDuplicateEvents(boolean srvFilterDup
* @return {@code this}
*/
DefaultDnsServiceDiscovererBuilder appendFilter(final DnsClientFilterFactory factory) {
filterFactory = filterFactory == null ? requireNonNull(factory) : filterFactory.append(factory);
requireNonNull(factory);
filterFactory = appendFilter(filterFactory, factory);
return this;
}

// Use another method to keep final references and avoid StackOverflowError
private static DnsClientFilterFactory appendFilter(@Nullable final DnsClientFilterFactory current,
final DnsClientFilterFactory next) {
return current == null ? next : dnsClient -> current.create(next.create(dnsClient));
}

/**
* Create a new instance of {@link DnsClient}.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2020 Apple Inc. and the ServiceTalk project authors
* 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.
Expand All @@ -15,8 +15,6 @@
*/
package io.servicetalk.dns.discovery.netty;

import static java.util.Objects.requireNonNull;

/**
* Factory to apply a {@link DnsClientFilter}s.
*/
Expand All @@ -29,27 +27,4 @@ interface DnsClientFilterFactory {
* @return {@link DnsClientFilter} using the provided {@link DnsClient}.
*/
DnsClientFilter create(DnsClient dnsClient);

/**
* Returns a composed function that first applies the {@code before} function to its input, and then applies
* this function to the result.
* <p>
* The order of execution of these filters are in order of append. If 3 filters are added as follows:
* <pre>
* filter1.append(filter2).append(filter3)
* </pre>
* making a request to a service discoverer wrapped by this filter chain the order of invocation of these filters
* will be:
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; service discoverer
* </pre>
*
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
*/
default DnsClientFilterFactory append(DnsClientFilterFactory before) {
requireNonNull(before);
return serviceDiscoverer -> create(before.create(serviceDiscoverer));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2019, 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.
Expand Down Expand Up @@ -100,10 +100,11 @@ public final Single<ServerContext> bind(final ServerBinder binder, final Executi
* @return {@code this}
*/
public GrpcServiceFactory<Filter, Service, FilterFactory> appendServiceFilter(FilterFactory before) {
requireNonNull(before);
if (filterFactory == null) {
filterFactory = before;
} else {
this.filterFactory = appendServiceFilterFactory(filterFactory, requireNonNull(before));
this.filterFactory = appendServiceFilterFactory(filterFactory, before);
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2019, 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.
Expand Down Expand Up @@ -47,9 +47,11 @@ public interface GrpcServiceFilterFactory<Filter extends Service, Service> {
* filter1 =&gt; filter2 =&gt; filter3 =&gt; service
* </pre>
*
* @deprecated Use {@link GrpcServiceFactory#appendServiceFilter(GrpcServiceFilterFactory)}
* @param before the factory to apply before this factory is applied.
* @return a composed factory that first applies the {@code before} factory and then applies this factory.
*/
@Deprecated
default GrpcServiceFilterFactory<Filter, Service> append(
GrpcServiceFilterFactory<Filter, Service> before) {
requireNonNull(before);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018-2020 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018-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.
Expand Down Expand Up @@ -41,6 +41,7 @@
import static io.servicetalk.http.api.HttpExecutionStrategyInfluencer.defaultStreamingInfluencer;
import static io.servicetalk.http.api.StrategyInfluencerAwareConversions.toConditionalServiceFilterFactory;
import static io.servicetalk.transport.api.ConnectionAcceptor.ACCEPT_ALL;
import static java.util.Objects.requireNonNull;

/**
* A builder for building HTTP Servers.
Expand Down Expand Up @@ -239,11 +240,8 @@ public final HttpServerBuilder appendConnectionAcceptorFilter(final ConnectionAc
* @return {@code this}
*/
public final HttpServerBuilder appendServiceFilter(final StreamingHttpServiceFilterFactory factory) {
if (serviceFilter == null) {
serviceFilter = factory;
} else {
serviceFilter = serviceFilter.append(factory);
}
requireNonNull(factory);
serviceFilter = appendFilter(serviceFilter, factory);
if (!influencerChainBuilder.appendIfInfluencer(factory)) {
influencerChainBuilder.append(defaultStreamingInfluencer());
}
Expand Down Expand Up @@ -451,11 +449,17 @@ private Single<ServerContext> listenForService(StreamingHttpService rawService,
StreamingHttpServiceFilterFactory currServiceFilter = serviceFilter;
if (!AsyncContext.isDisabled()) {
StreamingHttpServiceFilterFactory asyncContextFilter = new AsyncContextAwareHttpServiceFilter();
currServiceFilter = currServiceFilter == null ?
asyncContextFilter : asyncContextFilter.append(currServiceFilter);
currServiceFilter = currServiceFilter == null ? asyncContextFilter :
appendFilter(asyncContextFilter, currServiceFilter);
}
StreamingHttpService filteredService = currServiceFilter != null ?
currServiceFilter.create(rawService) : rawService;
return doListen(connectionAcceptor, filteredService, strategy, drainRequestPayloadBody);
}

private static StreamingHttpServiceFilterFactory appendFilter(
@Nullable final StreamingHttpServiceFilterFactory current,
final StreamingHttpServiceFilterFactory next) {
return current == null ? next : service -> current.create(next.create(service));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018-2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018-2019, 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.
Expand Down Expand Up @@ -54,9 +54,12 @@ public interface MultiAddressHttpClientFilterFactory<U> {
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; client
* </pre>
*
* @deprecated Use {@link MultiAddressHttpClientBuilder#appendClientFilter(MultiAddressHttpClientFilterFactory)}
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before} function and then applies this function
*/
@Deprecated
default MultiAddressHttpClientFilterFactory<U> append(MultiAddressHttpClientFilterFactory<U> before) {
requireNonNull(before);
return (group, client) -> create(group, before.create(group, client));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018-2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018-2019, 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.
Expand Down Expand Up @@ -44,10 +44,13 @@ public interface StreamingHttpClientFilterFactory {
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; client
* </pre>
*
* @deprecated Use {@link HttpClientBuilder#appendClientFilter(StreamingHttpClientFilterFactory)}
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
*/
@Deprecated
default StreamingHttpClientFilterFactory append(StreamingHttpClientFilterFactory before) {
requireNonNull(before);
return client -> create(before.create(client));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018, 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.
Expand Down Expand Up @@ -44,10 +44,13 @@ public interface StreamingHttpConnectionFilterFactory {
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; connection
* </pre>
*
* @deprecated Use {@link HttpClientBuilder#appendConnectionFilter(StreamingHttpConnectionFilterFactory)}
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
*/
@Deprecated
default StreamingHttpConnectionFilterFactory append(StreamingHttpConnectionFilterFactory before) {
requireNonNull(before);
return connection -> create(before.create(connection));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018, 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.
Expand Down Expand Up @@ -43,10 +43,13 @@ public interface StreamingHttpServiceFilterFactory {
* <pre>
* filter1 =&gt; filter2 =&gt; filter3 =&gt; service
* </pre>
*
* @deprecated Use {@link HttpServerBuilder#appendServiceFilter(StreamingHttpServiceFilterFactory)}
* @param before the function to apply before this function is applied
* @return a composed function that first applies the {@code before}
* function and then applies this function
*/
@Deprecated
default StreamingHttpServiceFilterFactory append(StreamingHttpServiceFilterFactory before) {
requireNonNull(before);
return service -> create(before.create(service));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018-2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018-2019, 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.
Expand All @@ -21,6 +21,8 @@

import java.util.concurrent.atomic.AtomicBoolean;

import static io.servicetalk.http.api.FilterFactoryUtils.appendClientFilterFactory;

public class ConditionalHttpClientFilterTest extends AbstractConditionalHttpFilterTest {

private static final StreamingHttpClientFilterFactory REQ_FILTER = client -> new StreamingHttpClientFilter(client) {
Expand Down Expand Up @@ -64,7 +66,7 @@ public Completable closeAsyncGracefully() {

public static StreamingHttpClient newClient(AtomicBoolean closed) {
return TestStreamingHttpClient.from(REQ_RES_FACTORY, testHttpExecutionContext(),
new TestCondFilterFactory(closed).append(REQ_FILTER));
appendClientFilterFactory(new TestCondFilterFactory(closed), REQ_FILTER));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2018 Apple Inc. and the ServiceTalk project authors
* Copyright © 2018, 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.
Expand All @@ -21,6 +21,7 @@

import java.util.concurrent.atomic.AtomicBoolean;

import static io.servicetalk.http.api.FilterFactoryUtils.appendConnectionFilterFactory;
import static org.mockito.Mockito.mock;

public class ConditionalHttpConnectionFilterTest extends AbstractConditionalHttpFilterTest {
Expand Down Expand Up @@ -65,9 +66,10 @@ public Completable closeAsyncGracefully() {
}
}

private StreamingHttpConnection newConnection(AtomicBoolean closed) {
private static StreamingHttpConnection newConnection(AtomicBoolean closed) {
return TestStreamingHttpConnection.from(REQ_RES_FACTORY, testHttpExecutionContext(),
mock(HttpConnectionContext.class), new TestCondFilterFactory(closed).append(REQ_FILTER));
mock(HttpConnectionContext.class),
appendConnectionFilterFactory(new TestCondFilterFactory(closed), REQ_FILTER));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
import static io.servicetalk.http.api.AbstractHttpRequesterFilterTest.RequesterType.ReservedConnection;
import static io.servicetalk.http.api.AbstractHttpRequesterFilterTest.SecurityType.Insecure;
import static io.servicetalk.http.api.AbstractHttpRequesterFilterTest.SecurityType.Secure;
import static io.servicetalk.http.api.FilterFactoryUtils.appendClientFilterFactory;
import static io.servicetalk.http.api.FilterFactoryUtils.appendConnectionFilterFactory;
import static io.servicetalk.http.api.HttpProtocolVersion.HTTP_1_1;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.mock;
Expand Down Expand Up @@ -332,12 +334,13 @@ private StreamingHttpConnection newConnection(final RequestWithContextHandler rw
@Override
public Single<StreamingHttpResponse> request(final HttpExecutionStrategy strategy,
final StreamingHttpRequest request) {
return rwch.request(AbstractHttpRequesterFilterTest.REQ_RES_FACTORY, connectionContext(), request);
return rwch.request(REQ_RES_FACTORY, connectionContext(), request);
}
};

return TestStreamingHttpConnection.from(AbstractHttpRequesterFilterTest.REQ_RES_FACTORY, mockExecutionContext,
mockConnectionContext, filterFactory == null ? handlerFilter : filterFactory.append(handlerFilter));
return TestStreamingHttpConnection.from(REQ_RES_FACTORY, mockExecutionContext,
mockConnectionContext, filterFactory == null ? handlerFilter :
appendConnectionFilterFactory(filterFactory, handlerFilter));
}

private <FF extends StreamingHttpClientFilterFactory & StreamingHttpConnectionFilterFactory> StreamingHttpClient
Expand All @@ -348,7 +351,7 @@ public Single<StreamingHttpResponse> request(final HttpExecutionStrategy strateg
protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate,
final HttpExecutionStrategy strategy,
final StreamingHttpRequest request) {
return rh.request(AbstractHttpRequesterFilterTest.REQ_RES_FACTORY, request);
return rh.request(REQ_RES_FACTORY, request);
}

@Override
Expand All @@ -368,6 +371,7 @@ protected Single<StreamingHttpResponse> request(
}
};

return TestStreamingHttpClient.from(REQ_RES_FACTORY, mockExecutionContext, filterFactory.append(handlerFilter));
return TestStreamingHttpClient.from(REQ_RES_FACTORY, mockExecutionContext,
appendClientFilterFactory(filterFactory, handlerFilter));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright © 2019 Apple Inc. and the ServiceTalk project authors
* Copyright © 2019, 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.
Expand All @@ -17,6 +17,9 @@

import java.util.function.Predicate;

import static io.servicetalk.http.api.FilterFactoryUtils.appendClientFilterFactory;
import static io.servicetalk.http.api.FilterFactoryUtils.appendConnectionFilterFactory;

public final class ConditionalFilterFactory
implements StreamingHttpConnectionFilterFactory, StreamingHttpClientFilterFactory {
private final Predicate<StreamingHttpRequest> predicate;
Expand All @@ -39,8 +42,8 @@ public StreamingHttpConnectionFilter create(final FilterableStreamingHttpConnect
}

public FilterFactory append(FilterFactory append) {
StreamingHttpClientFilterFactory clientFactory = append((StreamingHttpClientFilterFactory) append);
StreamingHttpConnectionFilterFactory connectionFactory = append((StreamingHttpConnectionFilterFactory) append);
StreamingHttpClientFilterFactory clientFactory = appendClientFilterFactory(this, append);
StreamingHttpConnectionFilterFactory connectionFactory = appendConnectionFilterFactory(this, append);
return new FilterFactory() {
@Override
public StreamingHttpClientFilter create(final FilterableStreamingHttpClient client) {
Expand Down
Loading

0 comments on commit 6f0d87f

Please sign in to comment.