Skip to content

Commit

Permalink
feat: native Spring Web workloads (aws#335) - native and non-native H…
Browse files Browse the repository at this point in the history
…andler should use same processing logic
  • Loading branch information
deki committed Jan 26, 2024
1 parent cb17885 commit 3ef9aab
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public class AsyncInitializationWrapper extends InitializationWrapper {
private static final boolean ASYNC_INIT_DISABLED = !INITIALIZATION_TYPE.equals(INITIALIZATION_TYPE_ON_DEMAND);
private static final int INIT_GRACE_TIME_MS = Integer.parseInt(System.getenv().getOrDefault(
INIT_GRACE_TIME_ENVIRONMENT_VARIABLE_NAME, Integer.toString(DEFAULT_INIT_GRACE_TIME_MS)));
public static final int LAMBDA_MAX_INIT_TIME_MS = 10_000;
private static final int LAMBDA_MAX_INIT_TIME_MS = 10_000;

private CountDownLatch initializationLatch;
private final long actualStartTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,22 @@
class AwsSpringHttpProcessingUtils {

private static Log logger = LogFactory.getLog(AwsSpringHttpProcessingUtils.class);
private static final int LAMBDA_MAX_REQUEST_DURATION_MINUTES = 15;

private AwsSpringHttpProcessingUtils() {

}

public static AwsProxyResponse processRequest(String gatewayEvent, ServerlessMVC mvc, ObjectMapper mapper, AwsProxyHttpServletResponseWriter responseWriter) {
HttpServletRequest request = AwsSpringHttpProcessingUtils.generateHttpServletRequest(gatewayEvent, null, mvc.getServletContext(), mapper);
public static AwsProxyResponse processRequest(HttpServletRequest request, ServerlessMVC mvc,
AwsProxyHttpServletResponseWriter responseWriter) {
CountDownLatch latch = new CountDownLatch(1);
AwsHttpServletResponse response = new AwsHttpServletResponse(request, latch);
try {
mvc.service(request, response);
latch.await(AsyncInitializationWrapper.LAMBDA_MAX_INIT_TIME_MS, TimeUnit.SECONDS);
boolean requestTimedOut = !latch.await(LAMBDA_MAX_REQUEST_DURATION_MINUTES, TimeUnit.MINUTES); // timeout is potentially lower as user configures it
if (requestTimedOut) {
logger.warn("request timed out after " + LAMBDA_MAX_REQUEST_DURATION_MINUTES + " minutes");
}
AwsProxyResponse awsResponse = responseWriter.writeResponse(response, null);
return awsResponse;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,10 @@ private void eventLoop(ServletWebServerApplicationContext context) {

try {
logger.debug("Submitting request to the user's web application");

AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest(incomingEvent.getBody(), mvc, mapper, responseWriter);

AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest(
AwsSpringHttpProcessingUtils.generateHttpServletRequest(incomingEvent.getBody(),
null, mvc.getServletContext(), mapper), mvc, responseWriter);
if (logger.isDebugEnabled()) {
logger.debug("Received response - body: " + awsResponse.getBody() +
"; status: " + awsResponse.getStatusCode() + "; headers: " + awsResponse.getHeaders());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import com.amazonaws.serverless.proxy.model.AwsProxyResponse;
import org.springframework.cloud.function.serverless.web.FunctionClassUtils;
import org.springframework.cloud.function.serverless.web.ServerlessMVC;

import com.amazonaws.serverless.proxy.internal.servlet.AwsHttpServletResponse;
import com.amazonaws.serverless.proxy.internal.servlet.AwsProxyHttpServletResponseWriter;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestStreamHandler;
Expand Down Expand Up @@ -63,15 +61,7 @@ public SpringDelegatingLambdaContainerHandler(Class<?>... startupClasses) {
public void handleRequest(InputStream input, OutputStream output, Context lambdaContext) throws IOException {
HttpServletRequest httpServletRequest = AwsSpringHttpProcessingUtils
.generateHttpServletRequest(input, lambdaContext, this.mvc.getServletContext(), this.mapper);
CountDownLatch latch = new CountDownLatch(1);
AwsHttpServletResponse httpServletResponse = new AwsHttpServletResponse(httpServletRequest, latch);
try {
this.mvc.service(httpServletRequest, httpServletResponse);
latch.await(10, TimeUnit.SECONDS);
this.mapper.writeValue(output, responseWriter.writeResponse(httpServletResponse, lambdaContext));
}
catch (Exception e) {
throw new IllegalStateException(e);
}
AwsProxyResponse awsProxyResponse = AwsSpringHttpProcessingUtils.processRequest(httpServletRequest, mvc, responseWriter);
this.mapper.writeValue(output, awsProxyResponse);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,9 @@ public void validateRequestResponse(String jsonEvent) throws Exception {
try (ConfigurableApplicationContext context = SpringApplication.run(EmptyApplication.class);) {
ServerlessMVC mvc = ServerlessMVC.INSTANCE((ServletWebServerApplicationContext) context);
AwsProxyHttpServletResponseWriter responseWriter = new AwsProxyHttpServletResponseWriter();
AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest(jsonEvent, mvc, mapper, responseWriter);
AwsProxyResponse awsResponse = AwsSpringHttpProcessingUtils.processRequest(
AwsSpringHttpProcessingUtils.generateHttpServletRequest(jsonEvent, null,
mvc.getServletContext(), mapper), mvc, responseWriter);
assertEquals("hello", awsResponse.getBody());
assertEquals(200, awsResponse.getStatusCode());
}
Expand Down

0 comments on commit 3ef9aab

Please sign in to comment.