Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .brazil.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@
"crt-unavailable-tests": { "skipImport": true },
"bundle-shading-tests": { "skipImport": true },
"architecture-tests": {"skipImport": true},
"s3-tests": {"skipImport": true}
"s3-tests": {"skipImport": true},
"warmup-tests": { "skipImport": true }
},

"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dependency-cve-monitor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
maven-args: >-
-DtransitiveExcludes=*:*
-DclasspathScope=runtime
-pl !build-tools,!release-scripts,!archetypes,!test/test-utils,!test/sdk-benchmarks,!test/http-client-tests,!test/http-client-benchmarks,!test/s3-benchmarks,!test/protocol-tests-core,!test/ruleset-testing-core,!test/protocol-tests,!test/service-test-utils,!test/codegen-generated-classes-test,!test/sdk-standard-benchmarks,!test/module-path-tests,!test/tests-coverage-reporting,!test/stability-tests,!test/sdk-native-image-test,!test/auth-tests,!test/region-testing,!test/old-client-version-compatibility-test,!test/bundle-logging-bridge-binding-test,!test/v2-migration-tests,!test/bundle-shading-tests,!test/crt-unavailable-tests,!test/architecture-tests,!test/s3-tests
-pl !build-tools,!release-scripts,!archetypes,!test/test-utils,!test/sdk-benchmarks,!test/http-client-tests,!test/http-client-benchmarks,!test/s3-benchmarks,!test/protocol-tests-core,!test/ruleset-testing-core,!test/protocol-tests,!test/service-test-utils,!test/codegen-generated-classes-test,!test/sdk-standard-benchmarks,!test/module-path-tests,!test/tests-coverage-reporting,!test/stability-tests,!test/sdk-native-image-test,!test/auth-tests,!test/region-testing,!test/old-client-version-compatibility-test,!test/bundle-logging-bridge-binding-test,!test/v2-migration-tests,!test/bundle-shading-tests,!test/crt-unavailable-tests,!test/architecture-tests,!test/s3-tests,!test/warmup-tests

notify-alerts:
if: github.repository == 'aws/aws-sdk-java-v2'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import software.amazon.awssdk.annotations.SdkPublicApi;
import software.amazon.awssdk.annotations.ThreadSafe;
import software.amazon.awssdk.core.internal.crac.ClasspathWarmUpInvoker;
import software.amazon.awssdk.core.internal.http.loader.ClasspathHttpWarmupInvoker;

/**
* Entry point for warming up SDK service request paths before a Coordinated Restore at Checkpoint (CRaC)
Expand Down Expand Up @@ -66,6 +67,7 @@ public static void prime() {
}
// Set primed only after invokeAll() succeeds, so a failed run leaves primed false and a later call retries.
ClasspathWarmUpInvoker.create().invokeAll();
ClasspathHttpWarmupInvoker.create().invokeAll();
primed = true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@

package software.amazon.awssdk.core.internal.crac;

import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.SdkTestInternalApi;
import software.amazon.awssdk.core.crac.SdkWarmUpProvider;
import software.amazon.awssdk.utils.Logger;

/**
* {@link WarmUpInvoker} implementation that uses {@link ServiceLoader} to find {@link SdkWarmUpProvider}
Expand All @@ -30,8 +27,6 @@
@SdkInternalApi
public final class ClasspathWarmUpInvoker implements WarmUpInvoker {

private static final Logger log = Logger.loggerFor(ClasspathWarmUpInvoker.class);

private final WarmUpServiceLoader serviceLoader;

@SdkTestInternalApi
Expand All @@ -41,30 +36,7 @@ public final class ClasspathWarmUpInvoker implements WarmUpInvoker {

@Override
public void invokeAll() {
Iterator<SdkWarmUpProvider> iterator = serviceLoader.loadProviders();
boolean invokedAny = false;

while (iterator.hasNext()) {
SdkWarmUpProvider provider;
try {
provider = iterator.next();
} catch (ServiceConfigurationError e) {
// next() has already advanced past the bad provider, so it is safe to continue to the next one.
log.warn(() -> "Skipping an SdkWarmUpProvider that could not be loaded.", e);
continue;
}

invokedAny = true;
try {
provider.warmUp();
} catch (RuntimeException e) {
log.warn(() -> "An SdkWarmUpProvider failed during warmUp() and was skipped.", e);
}
}

if (!invokedAny) {
log.debug(() -> "No SdkWarmUpProvider implementations were discovered on the classpath.");
}
WarmUpDiscovery.forEachDiscovered(serviceLoader.loadProviders(), SdkWarmUpProvider::warmUp);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.core.internal.crac;

import java.net.URI;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.core.SdkSystemSetting;
import software.amazon.awssdk.utils.HostnameValidator;
import software.amazon.awssdk.utils.Logger;
import software.amazon.awssdk.utils.StringUtils;

/**
* Resolves the endpoint used by the CRaC HTTP-client warm-up. The warm-up targets a single predetermined service; that service
* is currently STS, so this builds the regional STS endpoint ({@code https://sts.<region>.amazonaws.com/}).
*
* <p>The region is taken from {@link SdkSystemSetting#AWS_REGION} (the {@code aws.region} system property or {@code AWS_REGION}
* environment variable), falling back to {@value #DEFAULT_REGION} when it is unset or not a valid hostname component. This
* matches how the SDK resolves a region from system settings.
*
* <p>Only system properties and environment variables are read. The full SDK region-resolution chain (IMDS, profile file) is
* avoided during priming because those add network or filesystem calls that may fail or time out. The endpoint host always
* uses the {@code amazonaws.com} suffix, which is incorrect for the China, GovCloud, and ISO partitions; in those partitions
* the warm-up request simply fails and is ignored, since it is best-effort.
*/
@SdkInternalApi
public final class RegionEndpointResolver {

static final String DEFAULT_REGION = "us-east-1";

private static final Logger log = Logger.loggerFor(RegionEndpointResolver.class);

private RegionEndpointResolver() {
}

public static RegionEndpointResolver create() {
return new RegionEndpointResolver();
}

/**
* @return the regional STS endpoint URI for the resolved region; never null.
*/
public URI endpoint() {
return URI.create("https://sts." + resolveRegion() + ".amazonaws.com/");
}

private String resolveRegion() {
// trimToNull turns blank/empty into null so a blank AWS_REGION falls through to the default.
String awsRegion = SdkSystemSetting.AWS_REGION.getStringValue()
.map(StringUtils::trimToNull)
.orElse(null);
if (awsRegion == null) {
return DEFAULT_REGION;
}
// A real region is a hostname-compliant token. Reject anything else so it cannot alter the endpoint host, and fall
// back to the default so the best-effort warm-up still runs.
try {
HostnameValidator.validateHostnameCompliant(awsRegion, "region", "AWS_REGION");
return awsRegion;
} catch (IllegalArgumentException e) {
log.debug(() -> "Configured region is not a valid hostname component; using " + DEFAULT_REGION + " for warm-up.", e);
return DEFAULT_REGION;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.core.internal.crac;

import java.util.Iterator;
import java.util.ServiceConfigurationError;
import java.util.function.Consumer;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.utils.Logger;

/**
* Shared best-effort {@link java.util.ServiceLoader} iteration for the CRaC warm-up paths.
*/
@SdkInternalApi
public final class WarmUpDiscovery {

private static final Logger log = Logger.loggerFor(WarmUpDiscovery.class);

private WarmUpDiscovery() {
}

/**
* Applies {@code action} to every discovered element, skipping (and logging at warn) any element that fails to load or
* whose action throws, so the rest still run. Logs at debug when nothing is discovered.
*/
public static <T> void forEachDiscovered(Iterator<T> iterator, Consumer<T> action) {
boolean discoveredAny = false;
while (iterator.hasNext()) {
T element;
try {
element = iterator.next();
} catch (ServiceConfigurationError e) {
// next() has already advanced past the bad element, so it is safe to continue to the next one.
log.warn(() -> "Skipping a warm-up task that could not be loaded.", e);
continue;
}

discoveredAny = true;
T discovered = element;
try {
action.accept(discovered);
} catch (RuntimeException | LinkageError e) {
// LinkageError because a discovered element can fail to link (missing deps/native lib, failed static init),
// which is an Error, not an Exception. Skip it to keep warm-up best-effort; fatal Errors still propagate.
log.warn(() -> "Warm-up failed for " + discovered.getClass().getName() + " and was skipped.", e);
}
}

if (!discoveredAny) {
log.debug(() -> "No warm-up tasks were discovered on the classpath.");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.core.internal.http.loader;

import java.util.Collections;
import java.util.List;
import software.amazon.awssdk.annotations.SdkInternalApi;
import software.amazon.awssdk.annotations.SdkTestInternalApi;

/**
* {@link HttpWarmupInvoker} that owns the set of {@link HttpClientWarmer}s and invokes each.
*/
@SdkInternalApi
public final class ClasspathHttpWarmupInvoker implements HttpWarmupInvoker {

private final List<HttpClientWarmer> warmers;

@SdkTestInternalApi
ClasspathHttpWarmupInvoker(List<HttpClientWarmer> warmers) {
this.warmers = warmers;
}

/**
* @return an invoker over the HTTP-client warmers on the classpath.
*/
public static HttpWarmupInvoker create() {
return new ClasspathHttpWarmupInvoker(Collections.singletonList(SyncHttpClientWarmer.create()));
}

@Override
public void invokeAll() {
for (HttpClientWarmer warmer : warmers) {
warmer.warmAll();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.core.internal.http.loader;

import software.amazon.awssdk.annotations.SdkInternalApi;

/**
* Warms the sync or async HTTP clients on the classpath for CRaC priming.
*/
@SdkInternalApi
public interface HttpClientWarmer {

/**
* Warms every HTTP client found on the classpath. Best-effort; never throws.
*/
void warmAll();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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 software.amazon.awssdk.core.internal.http.loader;

import software.amazon.awssdk.annotations.SdkInternalApi;

/**
* Warms every HTTP client on the classpath for CRaC priming by invoking each {@link HttpClientWarmer}.
*/
@SdkInternalApi
public interface HttpWarmupInvoker {

/**
* Invokes {@link HttpClientWarmer#warmAll()} on every warmer. Best-effort; never throws.
*/
void invokeAll();
}
Loading
Loading