Skip to content

feat(sdk-core): add sync HTTP-client warm-up to SdkWarmUp.prime() for CRaC priming#7080

Merged
joviegas merged 8 commits into
feature/master/crac_auto_priming_supportfrom
joviegas/crac_warmup_orchestration_partB
Jun 30, 2026
Merged

feat(sdk-core): add sync HTTP-client warm-up to SdkWarmUp.prime() for CRaC priming#7080
joviegas merged 8 commits into
feature/master/crac_auto_priming_supportfrom
joviegas/crac_warmup_orchestration_partB

Conversation

@joviegas

@joviegas joviegas commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Motivation and Context

This change adds the second half of the hybrid priming approach: one real GET per sync HTTP client on the classpath, so that network path is JIT-compiled into the CRaC snapshot. It also adds the region/endpoint resolution shared with the future async warm-up.

Modifications

SdkWarmUp.prime() now runs the per-service providers and then the HTTP-client warm-up, both inside the existing idempotency guard. The HTTP-client warm-up is best-effort: a network failure during init is logged and swallowed so the rest of priming completes.

New internal types in sdk-core:

  • RegionEndpointResolver (internal.crac): resolves the region from the aws.region system property or AWS_REGION environment variable, falling back to us-east-1, and builds https://sts.<region>.amazonaws.com/. It reads only system properties and environment variables, avoiding the SDK region-resolution chain (IMDS, profile file) during priming. The region is validated with HostnameValidator; a value that is not a valid hostname component is rejected and the default region is used, so a malformed region cannot alter the endpoint host. AWS_DEFAULT_REGION is not consulted, matching how the SDK resolves a region from system settings for endpoints.
  • SyncHttpClientWarmer (internal.http.loader): discovers every sync SdkHttpService through the existing package-private SdkServiceLoader, builds each client, sends the warm-up GET, drains the response body, and closes the client.
  • WarmUpDiscovery: the discover-and-iterate loop shared by the per-service and HTTP-client warm-up. It skips an element that fails to load or run, including LinkageError (a client jar present without its transitive dependencies), so one broken element does not stop the others.
  • HttpClientWarmer interface plus HttpWarmupInvoker / ClasspathHttpWarmupInvoker: prime() calls one invoker that owns the set of warmers. The async warmer is added to that set later without changing SdkWarmUp or SyncHttpClientWarmer.

Tests for the warm-up against every sync HTTP client live in a new test/warmup-tests module rather than in each client module, avoiding the sdk-core -> apache-client -> http-client-tests -> sdk-core cyclic dependency.

Testing

Added Junits test

Screenshots (if appropriate)

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • [x ] New feature (non-breaking change which adds functionality)

License

  • I confirm that this pull request can be released under the Apache 2 license

@joviegas joviegas requested a review from a team as a code owner June 26, 2026 00:08
@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch 2 times, most recently from e4dfbde to 5b172b4 Compare June 26, 2026 15:17
@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch from 5b172b4 to 82c723b Compare June 26, 2026 15:29
@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch 2 times, most recently from bbf82e3 to 44b6b00 Compare June 26, 2026 16:43
public class Apache5HttpClientWarmUpTest {

@Rule
public WireMockRule mockServer = new WireMockRule(0);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We have a test for each HTTP client instead of a shared suite in test/http-client-tests. A shared suite there would create a cyclic dependency, because sdk-core has test dependencies on apache-client and netty-nio-client (sdk-core -> apache-client -> http-client-tests -> sdk-core). I filed JAVA-9020 to refactor this on master; once fixed, these tests can move to test/http-client-tests as a single SyncHttpClientWarmUpTestSuite shared across all HTTP clients.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A separate centralized package would be great, but maybe we can have a dedicated test package for testing CRaC components instead of using http-client-tests

Comment thread http-clients/apache5-client/pom.xml Outdated
<version>${awsjavasdk.version}</version>
<scope>test</scope>
</dependency>
<dependency>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch from 44b6b00 to 2f5b864 Compare June 26, 2026 18:26
}

// AWS_DEFAULT_REGION is an environment-variable-only fallback with no system-property equivalent.
private static final class AwsDefaultRegionEnvVar implements SystemSetting {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

AFAIK, we don't use AWS_DEFAULT_REGION for determining endpoints in the SDK (only DefaultsMode). Should we leave this out?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed it now

*/
public URI stsEndpoint() {
// URL-encode the region before putting it in the host, same as Region.of(String).
return URI.create("https://sts." + SdkHttpUtils.urlEncode(resolveRegion()) + ".amazonaws.com/");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

might benefit from using

public static void validateHostnameCompliant(String hostnameComponent, String paramName, String object) {
validateHostnameCompliant(hostnameComponent, paramName, object, DEFAULT_HOSTNAME_COMPLIANT_PATTERN);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

alternatively, build using the URI constructor will also validate it for correctness

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good call, adopted HostnameValidator. The region is now validated with validateHostnameCompliant; if it isn't a valid hostname component, we log and fall back to us-east-1 rather than propagate the exception, since endpoint resolution runs inside the best-effort warm-up and must not break priming.

Comment on lines +34 to +35
private final String body;
private final String contentType;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The ctor is private; are these necessary?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch, they weren't necessary. The class started as a small spec (method/body/content-type) intended to be shared by the sync and async warmers, but once the warm-up settled on a simple GET those fields were always null. I've removed WarmUpRequest entirely.

Comment on lines +29 to +30
* Resolves the regional STS endpoint ({@code https://sts.<region>.amazonaws.com/}) used by the CRaC HTTP-client warm-up.
*

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is this class intended to resolve other service endpoints in the future?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No. It is specific to whichever single service we pick for the warm-up (currently STS). It always returns one endpoint for that hardcoded service. If we later switch the warm-up to another service (e.g. DynamoDB), this class would build that endpoint instead. Renamed stsEndpoint() to endpoint() to reflect that.

* matters for JIT priming.
*/
@SdkInternalApi
public final class WarmUpRequest {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not really sure about the usefulness of this class. Does it make more sense to just have a utility class/factory just creates the HttpExecuteRequest directly?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

removed now

public class Apache5HttpClientWarmUpTest {

@Rule
public WireMockRule mockServer = new WireMockRule(0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A separate centralized package would be great, but maybe we can have a dedicated test package for testing CRaC components instead of using http-client-tests

@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch 3 times, most recently from 7421ffc to b4e9f64 Compare June 29, 2026 20:00
@joviegas joviegas force-pushed the joviegas/crac_warmup_orchestration_partB branch from b4e9f64 to 072736d Compare June 29, 2026 20:14
@joviegas joviegas merged commit 70fb508 into feature/master/crac_auto_priming_support Jun 30, 2026
3 checks passed
@github-actions

Copy link
Copy Markdown

This pull request has been closed and the conversation has been locked. Comments on closed PRs are hard for our team to see. If you need more assistance, please open a new issue that references this one.

@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Jun 30, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants