-
Notifications
You must be signed in to change notification settings - Fork 910
Endpoint Discovery for DynamoDb #853
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
Conversation
URI cachedEndpoint = endpointDiscoveryCache.get(key, | ||
testDiscoveryIdentifiersRequiredRequest.endpointDiscoveryRequest(), | ||
clientConfiguration.option(SdkClientOption.ENDPOINT)); | ||
clientConfiguration.copy(o -> o.option(SdkClientOption.ENDPOINT, cachedEndpoint)); |
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.
This doesn't change the original configuration. Also we don't want to update the client endpoint right as the new computed endpoint is only valid for that operation.
For endpoint trait, I am passing the hostPrefix to CientExecutionParams and modifying the endpoint in BaseClientHandler. But this is causing issues with path as its being modified multiple times. I am thinking of passing the hostprefix to marshallers and resolve the endpoint there before creating the HttpFullRequest.
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.
Ah, yes, was on a different version when I was doing this. Will update.
HttpResponseHandler<AwsServiceException> errorResponseHandler = createErrorResponseHandler(protocolFactory, | ||
operationMetadata); | ||
|
||
String key = clientConfiguration.option(AwsClientOption.CREDENTIALS_PROVIDER).resolveCredentials().accessKeyId(); |
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.
Would this not take into account request level credentials?
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.
Have same question
operationMetadata); | ||
|
||
String key = clientConfiguration.option(AwsClientOption.CREDENTIALS_PROVIDER).resolveCredentials().accessKeyId(); | ||
URI cachedEndpoint = endpointDiscoveryCache.get(key, |
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.
This cachedEndpoint doesn't appear to be used. Also for async this seems like it would be kind of blocking, at least for the first call.
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 would only be blocking if endpoint discovery is set as required. Otherwise we use the default endpoint. Is that correct?
core/aws-core/pom.xml
Outdated
@@ -33,6 +33,11 @@ | |||
<artifactId>auth</artifactId> | |||
<version>${awsjavasdk.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>software.amazon.awssdk</groupId> | |||
<artifactId>profiles</artifactId> |
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.
Why do we need this dependency?
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.
You can enable endpoint discovery through the profile file so I have a provider for it that requires the profiles module.
import software.amazon.awssdk.annotations.SdkInternalApi; | ||
|
||
@SdkInternalApi | ||
public class EndpointDiscoveryEndpoint { |
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.
Final
return builder().endpoint(endpoint).expirationTime(expirationTime); | ||
} | ||
|
||
public interface Builder { |
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 these extend any of that SdkBuilder copyable builder stuff?
} | ||
} | ||
|
||
if (endpoint.expirationTime().isBefore(Instant.now())) { |
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.
Does this mean it's already expired? If so are we returning the expired endpoint to the customer? Should we attempt to refresh it before it expires?
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.
Expired endpoints can be used until a 421 status code or InvalidEndpointException is thrown.
Once an endpoint is expired, we extend the expiration to 60 seconds and immediately attempt a refresh. We extend the expiration 60 seconds so that we aren't refreshing every time.
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.
Hmm gotcha. So expired means will become invalid soon?
return operationName; | ||
} | ||
|
||
public Optional<Map<String, String>> identifiers() { |
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 we copy and make this map unmodifiable in constructor?
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.
We certainly could but not sure if we need to given this is an internal use only class.
@SdkInternalApi | ||
public interface EndpointDiscoveryProvider { | ||
|
||
boolean resolveEndpointDiscovery(); |
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.
Can you add some docs here? I'm not sure what boolean is supposed to represent, I guess if endpoint discovery is enabled?
import software.amazon.awssdk.codegen.poet.PoetExtensions; | ||
import software.amazon.awssdk.codegen.poet.PoetUtils; | ||
|
||
public class EndpointDiscoveryCacheLoaderGenerator implements ClassSpec { |
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.
Can you add some code gen tests for this thing?
@@ -366,6 +372,15 @@ private MethodSpec getValueForField() { | |||
return methodBuilder.build(); | |||
} | |||
|
|||
private MethodSpec endpointDiscoveryRequest() { |
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.
Do we need to put this on the service model? Seems like an odd place for 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.
Any alternative suggestions?
If not on the generated models for the requests, we'd have to either generate a separate class per request or generate a list of which fields need to be pulled out for the identifiers for each request.
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.
This method is only called in the client. So what do you think about generating in the client method impl?
Code in cilent will change from
endpointDiscoveryCache.get(key,
listBackupsRequest.endpointDiscoveryRequest(),
clientConfiguration.option(SdkClientOption.ENDPOINT));
to
endpointDiscoveryCache.get(key,
EndpointDiscoveryRequest.builder().required(false).build(),
clientConfiguration.option(SdkClientOption.ENDPOINT));
Codecov Report
@@ Coverage Diff @@
## master #853 +/- ##
============================================
- Coverage 55.61% 55.58% -0.03%
- Complexity 4510 4566 +56
============================================
Files 799 810 +11
Lines 27487 27813 +326
Branches 2222 2241 +19
============================================
+ Hits 15286 15461 +175
- Misses 11488 11638 +150
- Partials 713 714 +1
Continue to review full report at Codecov.
|
|
||
for (OperationModel o : operations.values()) { | ||
if (o.isEndpointOperation()) { | ||
endpointOperation = o; |
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: we can break after finding the operation.
@@ -366,6 +372,15 @@ private MethodSpec getValueForField() { | |||
return methodBuilder.build(); | |||
} | |||
|
|||
private MethodSpec endpointDiscoveryRequest() { |
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.
This method is only called in the client. So what do you think about generating in the client method impl?
Code in cilent will change from
endpointDiscoveryCache.get(key,
listBackupsRequest.endpointDiscoveryRequest(),
clientConfiguration.option(SdkClientOption.ENDPOINT));
to
endpointDiscoveryCache.get(key,
EndpointDiscoveryRequest.builder().required(false).build(),
clientConfiguration.option(SdkClientOption.ENDPOINT));
operationMetadata); | ||
|
||
String key = clientConfiguration.option(AwsClientOption.CREDENTIALS_PROVIDER).resolveCredentials().accessKeyId(); | ||
URI cachedEndpoint = endpointDiscoveryCache.get(key, |
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 would only be blocking if endpoint discovery is set as required. Otherwise we use the default endpoint. Is that correct?
HttpResponseHandler<AwsServiceException> errorResponseHandler = createErrorResponseHandler(protocolFactory, | ||
operationMetadata); | ||
|
||
String key = clientConfiguration.option(AwsClientOption.CREDENTIALS_PROVIDER).resolveCredentials().accessKeyId(); |
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.
Have same question
if (endpoint.expirationTime().isBefore(Instant.now())) { | ||
cache.put(key, endpoint.toBuilder().expirationTime(Instant.now().plusSeconds(60)).build()); | ||
String finalKey = key; | ||
discoverEndpoint(null).thenApply(v -> cache.put(finalKey, v)); |
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.
Is passing null request to discoverEndpoint
method right?
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.
Changed to the request object.
return new BuilderImpl(this); | ||
} | ||
|
||
public interface Builder extends CopyableBuilder<Builder, EndpointDiscoveryRequest> { |
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.
Add docs?
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.
Will add.
@varunnvs92, can't reply to some of your comments for some reason. In the async client, it would only be blocking if endpoint discovery is required. Otherwise, it will be non-blocking. |
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.
LGTM
17d093b
to
78cc403
Compare
…e6bbd825 Pull request: release <- staging/fc650e8a-ed4f-453a-b1b1-4619e6bbd825
Supports the endpoint discovery spec for DynamoDb.