Skip to content

Adding AWS-CRT-Java 0.4.20 to AWS-SDK-Java-v2 #1607

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

Closed
wants to merge 44 commits into from

Conversation

rccarper
Copy link
Contributor

@rccarper rccarper commented Jan 22, 2020

Description

This was done by rebasing master onto crt-api-update, then rebasing crt-api-update onto aws-crt-dev-preview, making some additional changes to account for the latest CRT API, and then creating this branch. I'm open to merging this into aws-crt-dev-preview first if that's preferable to merging everything into master.

As such, there are a lot of changes here not done by myself. Only the changes done in commit f7a9464 are, in that sense, actually new. More detail about those changes:

  • This points the SDK to the latest build of the Java CRT available in Maven, ie, 0.4.19.
  • This required updating a handful of places where the API has changed.
  • I'm currently relying on the existing unit tests invoked by mvn clean install, and would be open to any other means of validating these changes if someone knows better.
  • Possible point for API discussion: the AwsCrtAsyncHttpClient now takes an EventLoopGroup and HostResolver via its builder. It would be possible to have the client create these objects itself, making a simpler experience for the user. However, because this does add the cost of an EventLoopGroup and HostResolver to each created AwsCrtAsyncHttpClient, and handling it for them potentially hides that cost, it seemed better to have the user explicitly specify their own. For example, a customer may use a pattern that creates a large number of clients, not realizing each client is spinning up an EventLoopGroup and HostResolver.

Testing

mvn clean install

[x ] I confirm that this pull request can be released under the Apache 2 license

@rccarper rccarper force-pushed the aws-crt-latest-api-update branch from 285e671 to f7a9464 Compare January 22, 2020 19:23
@rccarper rccarper changed the title Adding AWS CRT 0.4.19 to AWS Java V2 SDK Adding AWS-CRT-Java 0.4.19 to AWS-SDK-Java-v2 Jan 22, 2020
@codecov-io
Copy link

codecov-io commented Jan 22, 2020

Codecov Report

Merging #1607 into master will decrease coverage by 0.43%.
The diff coverage is 84.95%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1607      +/-   ##
============================================
- Coverage     76.34%   75.91%   -0.44%     
- Complexity      182      265      +83     
============================================
  Files          1070     1074       +4     
  Lines         32225    32301      +76     
  Branches       2520     2500      -20     
============================================
- Hits          24601    24520      -81     
- Misses         6388     6528     +140     
- Partials       1236     1253      +17     
Flag Coverage Δ Complexity Δ
#unittests 75.91% <84.95%> (-0.44%) 265.00 <83.00> (+83.00) ⬇️
Impacted Files Coverage Δ Complexity Δ
...http/crt/internal/AwsCrtRequestBodySubscriber.java 78.00% <78.00%> (ø) 12.00 <12.00> (?)
.../amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java 80.00% <80.00%> (ø) 22.00 <22.00> (?)
...http/crt/internal/AwsCrtResponseBodyPublisher.java 88.46% <88.46%> (ø) 31.00 <31.00> (?)
...ttp/crt/internal/AwsCrtAsyncHttpStreamAdapter.java 93.61% <93.61%> (ø) 13.00 <13.00> (?)
...p/crt/internal/AwsCrtResponseBodySubscription.java 100.00% <100.00%> (ø) 5.00 <5.00> (?)
...credentials/SystemPropertyCredentialsProvider.java 33.33% <0.00%> (-66.67%) 0.00% <0.00%> (ø%)
...ntials/EnvironmentVariableCredentialsProvider.java 33.33% <0.00%> (-66.67%) 0.00% <0.00%> (ø%)
...e/endpointdiscovery/EndpointDiscoveryEndpoint.java 0.00% <0.00%> (-64.71%) 0.00% <0.00%> (ø%)
...oftware/amazon/awssdk/regions/ServiceMetadata.java 36.36% <0.00%> (-63.64%) 0.00% <0.00%> (ø%)
...re/endpointdiscovery/EndpointDiscoveryRequest.java 0.00% <0.00%> (-59.46%) 0.00% <0.00%> (ø%)
... and 111 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0a69d0c...0a69d0c. Read the comment docs.

@rccarper rccarper force-pushed the aws-crt-latest-api-update branch 2 times, most recently from 4a72926 to d554587 Compare January 28, 2020 20:37
@rccarper rccarper force-pushed the aws-crt-latest-api-update branch from d554587 to d421878 Compare January 28, 2020 21:01
@sonarqubecloud
Copy link

Kudos, SonarCloud Quality Gate passed!

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 19 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@rccarper rccarper changed the title Adding AWS-CRT-Java 0.4.19 to AWS-SDK-Java-v2 Adding AWS-CRT-Java 0.4.20 to AWS-SDK-Java-v2 Mar 2, 2020
@alexw91
Copy link
Contributor

alexw91 commented Mar 31, 2020

I needed to make a small one line fix to get this to work with aws-crt-java v0.5.1: alexw91@025c43c

Feel free to incorporate that fix into this PR.

* @param windowSize The AWS Common Runtime WindowSize
* @return The builder of the method chaining.
*/
Builder windowSize(int windowSize);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rename this as it may confuse users when HTTP/2 support is added, which also has its own concept of a window size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

crtWindowSize enough or do we need something completely different?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think having windowSize at all in there would be confusing. As far as I understand, this is how much data the CRT client buffers for reads right? Maybe something like "pendingReadBuffer"? Or something along those lines.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On further investigation, this parameter will also control h/2 initial window size so it should remain the same. I'm going to change it to initialWindowSize though to more closely match its function.

* @param verifyPeer true if the Certificate Chain should be validated, false if validation should be skipped.
* @return The builder of the method chaining.
*/
Builder verifyPeer(boolean verifyPeer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should rely on the standard TRUST_ALL_CERTIFICATES options here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in the new PR

/**
* Builder that allows configuration of the AWS CRT HTTP implementation.
*/
public interface Builder extends SdkAsyncHttpClient.Builder<AwsCrtAsyncHttpClient.Builder> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the client have support for various timeout configurations? e.g. connection and read timeouts?

Proxy support is also an important one for customers

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have connection (socket) timeouts and throughput monitoring which technically is capable of expressing a read timeout is a specialization. Neither appear to be exposed here though.

Basic proxy support exists, but no socks yet. I'll look into exposing proxy configuration.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coo proxy support would be nice

private final int maxConnectionsPerEndpoint;


public AwsCrtAsyncHttpClient(DefaultBuilder builder, AttributeMap config) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be private

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in new PR

* <p>This can be created via {@link #builder()}</p>
*/
@SdkPublicApi
public class AwsCrtAsyncHttpClient implements SdkAsyncHttpClient {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make final

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in new PR


private List<HttpHeader> createHttpHeaderList(URI uri, AsyncExecuteRequest asyncRequest) {
SdkHttpRequest sdkRequest = asyncRequest.request();
List<HttpHeader> crtHeaderList = new ArrayList<>(sdkRequest.headers().size() + 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor: what's the reason for the + 2?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it's just a reserve on the potential extra headers added, but then again, there's 3 potential additions, so a little weird. Could change to 3 and add a note.


if (!wasFirstSubscriber) {
log.error(() -> "Only one subscriber allowed");
subscriber.onError(new IllegalStateException("Only one subscriber allowed"));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onSubscribe must be called before signalling onError. See 1.9: https://github.com/reactive-streams/reactive-streams-jvm/blob/v1.0.3/README.md

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure of the right way to proceed here. We only want one subscriber so should we just drop the onError signal and return, or drop it and throw the exception that was being pushed? The latter seems best, but I want to check first.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can still signal onError for all subscribers besides the first one. The spec just requires that onSubscribe is called before signalling anything. The typical way to handle this would be to simply call onSubscribe with a dummy Subscription:

if (!wasFirstSubscriber) {
    subscriber.onSubscribe(new DummySubscription());
    subscriber.onError(...);
}

This mentioned in the doc:

...for all other situations the only legal way to signal failure (or reject the Subscriber) is by calling onError (after calling onSubscribe).

* @param <T> The CrtResource Type
* @return The CrtResource passed in
*/
private <T extends CrtResource> T own(T subresource) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the type param needed? Can it just accept and return CrtResource?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do use the function as the right-hand value of assignment so technically it's used.


HttpHeader[] crtHeaderArray = asArray(createHttpHeaderList(uri, asyncRequest));

return new HttpRequest(method, encodedPath + encodedQueryString, crtHeaderArray, crtToSdkAdapter);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Encoded path may be null or empty here, I think we need to account for that here and defeault to / if so

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in new PR

Comment on lines +163 to +174
if (connPool == null) {
HttpClientConnectionManager newConnPool = createConnectionPool(uri);
HttpClientConnectionManager alreadyExistingConnPool = connectionPools.putIfAbsent(uri, newConnPool);

if (alreadyExistingConnPool == null) {
connPool = newConnPool;
} else {
// Multiple threads trying to open connections to the same URI at once, close the newer one
newConnPool.close();
connPool = alreadyExistingConnPool;
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it relatively expensive to create/close a connection pool? Given that this is not likely to be a highly contented call, it might be better to synchronize on create

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not connecting but it is creating a tls context. What kind of synchronization would you think appropriate? A single lock for the client when creating new pools?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just making the whole method synchronized would be fine. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Went with a slightly different approach: synchronized is used to make close() and getOrCreateConnectionPool() mutually exclusive, but we also add-ref on the returned pool and let a try-with-resources block perform the corresponding dec-ref on the pool after the request was submitted. Essentially in the time between when the pool was fetched and when the request was submitted, someone could call close and shutdown the pool from underneath us. This prevents that (in the sense that the pool won't shut down until the connection acquisition has been submitted).

@sonarqubecloud
Copy link

sonarqubecloud bot commented Apr 2, 2020

SonarCloud Quality Gate failed.

Bug C 1 Bug
Vulnerability A 0 Vulnerabilities (and Security Hotspot 0 Security Hotspots to review)
Code Smell A 18 Code Smells

80.3% 80.3% Coverage
3.4% 3.4% Duplication

@bretambrose bretambrose mentioned this pull request Apr 13, 2020
13 tasks
@codecov-commenter
Copy link

Codecov Report

Merging #1607 into master will increase coverage by 0.07%.
The diff coverage is 84.95%.

Impacted file tree graph

@@             Coverage Diff              @@
##             master    #1607      +/-   ##
============================================
+ Coverage     75.83%   75.91%   +0.07%     
- Complexity      182      265      +83     
============================================
  Files          1069     1074       +5     
  Lines         32033    32301     +268     
  Branches       2490     2500      +10     
============================================
+ Hits          24291    24520     +229     
- Misses         6510     6528      +18     
- Partials       1232     1253      +21     
Flag Coverage Δ Complexity Δ
#unittests 75.91% <84.95%> (+0.07%) 265.00 <83.00> (+83.00)

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ Complexity Δ
...http/crt/internal/AwsCrtRequestBodySubscriber.java 78.00% <78.00%> (ø) 12.00 <12.00> (?)
.../amazon/awssdk/http/crt/AwsCrtAsyncHttpClient.java 80.00% <80.00%> (ø) 22.00 <22.00> (?)
...http/crt/internal/AwsCrtResponseBodyPublisher.java 88.46% <88.46%> (ø) 31.00 <31.00> (?)
...ttp/crt/internal/AwsCrtAsyncHttpStreamAdapter.java 93.61% <93.61%> (ø) 13.00 <13.00> (?)
...p/crt/internal/AwsCrtResponseBodySubscription.java 100.00% <100.00%> (ø) 5.00 <5.00> (?)
.../awssdk/http/apache/internal/net/SdkSslSocket.java 36.36% <0.00%> (-22.73%) 0.00% <0.00%> (ø%)
...ssdk/core/internal/async/FileAsyncRequestBody.java 84.76% <0.00%> (-2.86%) 0.00% <0.00%> (ø%)
...ery/internal/marshall/QueryMarshallerRegistry.java 77.77% <0.00%> (-2.23%) 0.00% <0.00%> (ø%)
...awssdk/codegen/poet/client/specs/ProtocolSpec.java 81.57% <0.00%> (-2.15%) 0.00% <0.00%> (ø%)
.../amazon/awssdk/http/apache/ProxyConfiguration.java 49.03% <0.00%> (-0.97%) 0.00% <0.00%> (ø%)
... and 46 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2c22928...0a69d0c. Read the comment docs.

@dagnir
Copy link
Contributor

dagnir commented Nov 11, 2020

Replaced by #1777.

@dagnir dagnir closed this Nov 11, 2020
aws-sdk-java-automation added a commit that referenced this pull request Aug 13, 2021
…3b8c5e991

Pull request: release <- staging/f0def870-d7b7-4175-9377-2d03b8c5e991
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants