From 190c5477c27328204ee1db93dc5c40517d24d74a Mon Sep 17 00:00:00 2001 From: Vipin Gupta Date: Tue, 21 Jul 2026 12:39:39 +0000 Subject: [PATCH] feat(runtime-interface-client): Add Lambda-Runtime-Invocation-Id support for cross-wiring protection Echo the invocation ID received from RAPID on /next back on /response and /error, enabling RAPID to detect and reject stale responses from timed-out invocations. Fully backward compatible. --- .../RELEASE.CHANGELOG.md | 4 +++ .../pom.xml | 2 +- .../lambda/runtime/api/client/AWSLambda.java | 4 +-- .../runtimeapi/LambdaRuntimeApiClient.java | 6 ++-- .../LambdaRuntimeApiClientImpl.java | 19 +++++++---- .../api/client/runtimeapi/NativeClient.java | 2 +- .../runtimeapi/dto/InvocationRequest.java | 13 ++++++++ ...ime_api_client_runtimeapi_NativeClient.cpp | 18 +++++++++-- ...ntime_api_client_runtimeapi_NativeClient.h | 2 +- .../include/aws/lambda-runtime/runtime.h | 12 +++++-- .../deps/aws-lambda-cpp-0.2.7/src/runtime.cpp | 19 ++++++++--- .../runtime/api/client/AWSLambdaTest.java | 32 +++++++++---------- .../LambdaRuntimeApiClientImplTest.java | 12 +++---- 13 files changed, 99 insertions(+), 46 deletions(-) diff --git a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md index 2391045fc..97d177034 100644 --- a/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md +++ b/aws-lambda-java-runtime-interface-client/RELEASE.CHANGELOG.md @@ -1,3 +1,7 @@ +### July 17, 2026 +`2.12.0` +- Add `Lambda-Runtime-Invocation-Id` header support for cross-wiring protection. The RIC now echoes the invocation ID received from RAPID on `/next` back on `/response` and `/error`, enabling RAPID to detect and reject stale responses from timed-out invocations. + ### May 13, 2026 `2.11.0` - Update aws-lambda-java-serialization dependency to 1.4.1 diff --git a/aws-lambda-java-runtime-interface-client/pom.xml b/aws-lambda-java-runtime-interface-client/pom.xml index 2ba71c43c..78d634a4d 100644 --- a/aws-lambda-java-runtime-interface-client/pom.xml +++ b/aws-lambda-java-runtime-interface-client/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.amazonaws aws-lambda-java-runtime-interface-client - 2.11.0 + 2.12.0 jar AWS Lambda Java Runtime Interface Client diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java index e5b221a80..b9aa0fd11 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java +++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambda.java @@ -315,7 +315,7 @@ private static void startRuntimeLoop(LambdaRequestHandler lambdaRequestHandler, try { ByteArrayOutputStream payload = lambdaRequestHandler.call(request); - runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray()); + runtimeClient.reportInvocationSuccess(request.getId(), payload.toByteArray(), request.getInvocationId()); // clear interrupted flag in case if it was set by user's code Thread.interrupted(); } catch (Throwable t) { @@ -323,7 +323,7 @@ private static void startRuntimeLoop(LambdaRequestHandler lambdaRequestHandler, userFault = UserFault.makeUserFault(t); shouldExit = exitLoopOnErrors && (t instanceof VirtualMachineError || t instanceof IOError || userFault.fatal); LambdaError error = createLambdaErrorFromThrowableOrUserFault(t); - runtimeClient.reportInvocationError(request.getId(), error); + runtimeClient.reportInvocationError(request.getId(), error, request.getInvocationId()); } finally { if (userFault != null) { lambdaLogger.log(userFault.reportableError(), lambdaLogger.getLogFormat() == LogFormat.JSON ? LogLevel.ERROR : LogLevel.UNDEFINED); diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java index a62aeb9b8..042bd2579 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java +++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClient.java @@ -34,15 +34,17 @@ public interface LambdaRuntimeApiClient { * Report invocation success * @param requestId request id * @param response byte array representing response + * @param invocationId invocation id for cross-wiring protection (may be null) */ - void reportInvocationSuccess(String requestId, byte[] response) throws IOException; + void reportInvocationSuccess(String requestId, byte[] response, String invocationId) throws IOException; /** * Report invocation error * @param requestId request id * @param error error to report + * @param invocationId invocation id for cross-wiring protection (may be null) */ - void reportInvocationError(String requestId, LambdaError error) throws IOException; + void reportInvocationError(String requestId, LambdaError error, String invocationId) throws IOException; /** * SnapStart endpoint to report that beforeCheckoint hooks were executed diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java index caca69aa7..25b454a0d 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java +++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImpl.java @@ -55,7 +55,7 @@ public LambdaRuntimeApiClientImpl(String hostnameAndPort) { @Override public void reportInitError(LambdaError error) throws IOException { String endpoint = this.baseUrl + "/2018-06-01/runtime/init/error"; - reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE); + reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, null); } @Override @@ -123,14 +123,15 @@ public InvocationRequest nextInvocationWithExponentialBackoff(LambdaContextLogge } @Override - public void reportInvocationSuccess(String requestId, byte[] response) { - NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response); + public void reportInvocationSuccess(String requestId, byte[] response, String invocationId) { + byte[] invocationIdBytes = invocationId != null ? invocationId.getBytes(UTF_8) : null; + NativeClient.postInvocationResponse(requestId.getBytes(UTF_8), response, invocationIdBytes); } @Override - public void reportInvocationError(String requestId, LambdaError error) throws IOException { + public void reportInvocationError(String requestId, LambdaError error, String invocationId) throws IOException { String endpoint = invocationEndpoint + requestId + "/error"; - reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE); + reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, invocationId); } @Override @@ -145,13 +146,17 @@ public void restoreNext() throws IOException { @Override public void reportRestoreError(LambdaError error) throws IOException { String endpoint = this.baseUrl + "/2018-06-01/runtime/restore/error"; - reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE); + reportLambdaError(endpoint, error, XRAY_ERROR_CAUSE_MAX_HEADER_SIZE, null); } - void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize) throws IOException { + void reportLambdaError(String endpoint, LambdaError error, int maxXrayHeaderSize, String invocationId) throws IOException { Map headers = new HashMap<>(); headers.put(ERROR_TYPE_HEADER, error.errorType.getRapidError()); + if (invocationId != null) { + headers.put("Lambda-Runtime-Invocation-Id", invocationId); + } + if (error.xRayErrorCause != null) { byte[] xRayErrorCauseJson = DtoSerializers.serialize(error.xRayErrorCause); if (xRayErrorCauseJson != null && xRayErrorCauseJson.length < maxXrayHeaderSize) { diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java index 101aea4d0..5c690814b 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java +++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/NativeClient.java @@ -21,6 +21,6 @@ static void init(String awsLambdaRuntimeApi) { static native InvocationRequest next(); - static native void postInvocationResponse(byte[] requestId, byte[] response); + static native void postInvocationResponse(byte[] requestId, byte[] response, byte[] invocationId); } diff --git a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java index 656945b41..a589cb024 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java +++ b/aws-lambda-java-runtime-interface-client/src/main/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/dto/InvocationRequest.java @@ -45,6 +45,11 @@ public class InvocationRequest { */ private String tenantId; + /** + * The invocation ID for cross-wiring protection. + */ + private String invocationId; + private byte[] content; public String getId() { @@ -107,6 +112,14 @@ public void setTenantId(String tenantId) { this.tenantId = tenantId; } + public String getInvocationId() { + return invocationId; + } + + public void setInvocationId(String invocationId) { + this.invocationId = invocationId; + } + public byte[] getContent() { return content; } diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp index f06796616..fb6cd3ca3 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp +++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.cpp @@ -21,6 +21,7 @@ static jfieldID clientContextField; static jfieldID cognitoIdentityField; static jfieldID xrayTraceIdField; static jfieldID tenantIdField; +static jfieldID invocationIdField; jint JNI_OnLoad(JavaVM* vm, void* reserved) { @@ -43,6 +44,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { clientContextField = env->GetFieldID(invocationRequestClass , "clientContext", "Ljava/lang/String;"); cognitoIdentityField = env->GetFieldID(invocationRequestClass , "cognitoIdentity", "Ljava/lang/String;"); tenantIdField = env->GetFieldID(invocationRequestClass, "tenantId", "Ljava/lang/String;"); + invocationIdField = env->GetFieldID(invocationRequestClass, "invocationId", "Ljava/lang/String;"); return JNI_VERSION; } @@ -112,6 +114,10 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_ CHECK_EXCEPTION(env, env->SetObjectField(invocationRequest, tenantIdField, env->NewStringUTF(response.tenant_id.c_str()))); } + if(response.invocation_id != ""){ + CHECK_EXCEPTION(env, env->SetObjectField(invocationRequest, invocationIdField, env->NewStringUTF(response.invocation_id.c_str()))); + } + bytes = reinterpret_cast(response.payload.c_str()); CHECK_EXCEPTION(env, jArray = env->NewByteArray(response.payload.length())); CHECK_EXCEPTION(env, env->SetByteArrayRegion(jArray, 0, response.payload.length(), bytes)); @@ -124,7 +130,7 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_ } JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_postInvocationResponse - (JNIEnv *env, jobject thisObject, jbyteArray jrequestId, jbyteArray jresponseArray) { + (JNIEnv *env, jobject thisObject, jbyteArray jrequestId, jbyteArray jresponseArray, jbyteArray jinvocationId) { std::string payload = toNativeString(env, jresponseArray); if ((env)->ExceptionOccurred()){ return; @@ -134,8 +140,16 @@ JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_run return; } + std::string invocationId; + if (jinvocationId != nullptr) { + invocationId = toNativeString(env, jinvocationId); + if ((env)->ExceptionOccurred()){ + return; + } + } + auto response = aws::lambda_runtime::invocation_response::success(payload, "application/json"); - auto outcome = CLIENT->post_success(requestId, response); + auto outcome = CLIENT->post_success(requestId, response, invocationId); if (!outcome.is_success()) { std::string errorMessage("Failed to post invocation response."); throwLambdaRuntimeClientException(env, errorMessage, outcome.get_failure()); diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h index 7219109b0..0f1aaa2ca 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h +++ b/aws-lambda-java-runtime-interface-client/src/main/jni/com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient.h @@ -17,7 +17,7 @@ JNIEXPORT jobject JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_ (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_com_amazonaws_services_lambda_runtime_api_client_runtimeapi_NativeClient_postInvocationResponse - (JNIEnv *, jobject, jbyteArray, jbyteArray); + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray); #ifdef __cplusplus } diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h index c4868c1ba..1e05e741b 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h +++ b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/include/aws/lambda-runtime/runtime.h @@ -66,6 +66,11 @@ struct invocation_request { */ std::string tenant_id; + /** + * Invocation ID for cross-wiring protection. + */ + std::string invocation_id; + /** * The number of milliseconds left before lambda terminates the current execution. */ @@ -154,12 +159,12 @@ class runtime { /** * Tells lambda that the function has succeeded. */ - post_outcome post_success(std::string const& request_id, invocation_response const& handler_response); + post_outcome post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id = ""); /** * Tells lambda that the function has failed. */ - post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response); + post_outcome post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id = ""); private: void set_curl_next_options(); @@ -167,7 +172,8 @@ class runtime { post_outcome do_post( std::string const& url, std::string const& request_id, - invocation_response const& handler_response); + invocation_response const& handler_response, + std::string const& invocation_id = ""); private: std::string const m_user_agent_header; diff --git a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp index 84a84b439..7d8d26a73 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp +++ b/aws-lambda-java-runtime-interface-client/src/main/jni/deps/aws-lambda-cpp-0.2.7/src/runtime.cpp @@ -41,6 +41,7 @@ static constexpr auto COGNITO_IDENTITY_HEADER = "lambda-runtime-cognito-identity static constexpr auto DEADLINE_MS_HEADER = "lambda-runtime-deadline-ms"; static constexpr auto FUNCTION_ARN_HEADER = "lambda-runtime-invoked-function-arn"; static constexpr auto TENANT_ID_HEADER = "lambda-runtime-aws-tenant-id"; +static constexpr auto INVOCATION_ID_HEADER = "lambda-runtime-invocation-id"; thread_local static CURL* m_curl_handle = curl_easy_init(); enum Endpoints { @@ -306,25 +307,30 @@ runtime::next_outcome runtime::get_next() if (resp.has_header(TENANT_ID_HEADER)) { req.tenant_id = resp.get_header(TENANT_ID_HEADER); } + + if (resp.has_header(INVOCATION_ID_HEADER)) { + req.invocation_id = resp.get_header(INVOCATION_ID_HEADER); + } return next_outcome(req); } -runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response) +runtime::post_outcome runtime::post_success(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id) { std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/response"; - return do_post(url, request_id, handler_response); + return do_post(url, request_id, handler_response, invocation_id); } -runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response) +runtime::post_outcome runtime::post_failure(std::string const& request_id, invocation_response const& handler_response, std::string const& invocation_id) { std::string const url = m_endpoints[Endpoints::RESULT] + request_id + "/error"; - return do_post(url, request_id, handler_response); + return do_post(url, request_id, handler_response, invocation_id); } runtime::post_outcome runtime::do_post( std::string const& url, std::string const& request_id, - invocation_response const& handler_response) + invocation_response const& handler_response, + std::string const& invocation_id) { set_curl_post_result_options(); curl_easy_setopt(lambda_runtime::m_curl_handle, CURLOPT_URL, url.c_str()); @@ -341,6 +347,9 @@ runtime::post_outcome runtime::do_post( headers = curl_slist_append(headers, "Expect:"); headers = curl_slist_append(headers, "transfer-encoding:"); headers = curl_slist_append(headers, m_user_agent_header.c_str()); + if (!invocation_id.empty()) { + headers = curl_slist_append(headers, ("lambda-runtime-invocation-id: " + invocation_id).c_str()); + } auto const& payload = handler_response.get_payload(); logging::log_debug( LOG_TAG, "calculating content length... %s", ("content-length: " + std::to_string(payload.length())).c_str()); diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java index 49b59c2cd..57cc782d2 100644 --- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java +++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/AWSLambdaTest.java @@ -242,7 +242,7 @@ void testConcurrentRunWithPlatformThreads() throws Throwable { AWSLambda.startRuntimeLoops(lambdaRequestHandler, lambdaLogger, concurrencyConfig, runtimeClient); // Success Reports Must Equal number of tasks that ran successfully. - verify(runtimeClient, times(7)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any()); + verify(runtimeClient, times(7)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any()); // Hashmap keys should equal the number of threads (runtime loops). assertEquals(4, SampleHandler.hashMap.size()); // Hashmap total count should equal all tasks that ran * number of iterations per task @@ -280,11 +280,11 @@ void testConcurrentRunWithPlatformThreadsWithFailures() throws Throwable { verify(lambdaLogger, times(6)).log(anyString(), eq(LogLevel.ERROR)); // Failed invokes should be reported. - verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any()); - verify(runtimeClient).reportInvocationError(eq(UserFaultID), any()); + verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any()); + verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any()); // Success Reports Must Equal number of tasks that ran successfully. - verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any()); + verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any()); // Hashmap keys should equal the minumum between(number of threads (runtime loops) AND number of tasks that ran successfully). assertEquals(2, SampleHandler.hashMap.size()); @@ -326,12 +326,12 @@ void testConcurrentModeLoopDoesNotExitExceptForLambdaRuntimeClientMaxRetriesExce verify(lambdaLogger, times(4)).log(anyString(), eq(LogLevel.ERROR)); // Failed invokes should be reported. - verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any()); - verify(runtimeClient).reportInvocationError(eq(UserFaultID), any()); - verify(runtimeClient).reportInvocationError(eq(IOErrorID), any()); + verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any()); + verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any()); + verify(runtimeClient).reportInvocationError(eq(IOErrorID), any(), any()); // Success Reports Must Equal number of tasks that ran successfully. - verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any()); + verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any()); // Hashmap keys should equal the minumum between(number of threads (runtime loops) AND number of tasks that ran successfully). assertEquals(1, SampleHandler.hashMap.size()); @@ -516,12 +516,12 @@ void testSequentialWithFatalUserFaultErrorStopsLoop() throws Throwable { verify(lambdaLogger, times(2)).log(anyString(), eq(LogLevel.ERROR)); // Failed invokes should be reported. - verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any()); - verify(runtimeClient).reportInvocationError(eq(UserFaultID), any()); + verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any()); + verify(runtimeClient).reportInvocationError(eq(UserFaultID), any(), any()); // Success Reports Must Equal number of tasks that ran successfully. And only 2 Error reports for failImmediatelyRequest and userFaultRequest. - verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any()); - verify(runtimeClient, times(2)).reportInvocationError(any(), any()); + verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any()); + verify(runtimeClient, times(2)).reportInvocationError(any(), any(), any()); // Hashmap keys should equal one as it is not multithreaded. assertEquals(1, SampleHandler.hashMap.size()); @@ -562,12 +562,12 @@ void testSequentialWithVirtualMachineErrorStopsLoop() throws Throwable { verify(lambdaLogger, times(2)).log(anyString(), eq(LogLevel.ERROR)); // Failed invokes should be reported. - verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any()); - verify(runtimeClient).reportInvocationError(eq(IOErrorID), any()); + verify(runtimeClient).reportInvocationError(eq(SampleHandler.FAIL_IMMEDIATELY_OP_MODE), any(), any()); + verify(runtimeClient).reportInvocationError(eq(IOErrorID), any(), any()); // Success Reports Must Equal number of tasks that ran successfully. And only 2 Error reports for failImmediatelyRequest and virtualMachineErrorRequest. - verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any()); - verify(runtimeClient, times(2)).reportInvocationError(any(), any()); + verify(runtimeClient, times(2)).reportInvocationSuccess(eq(SampleHandler.ADD_ENTRY_TO_MAP_ID_OP_MODE), any(), any()); + verify(runtimeClient, times(2)).reportInvocationError(any(), any(), any()); // Hashmap keys should equal one as it is not multithreaded. assertEquals(1, SampleHandler.hashMap.size()); diff --git a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java index 710c1565e..845f7160d 100644 --- a/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java +++ b/aws-lambda-java-runtime-interface-client/src/test/java/com/amazonaws/services/lambda/runtime/api/client/runtimeapi/LambdaRuntimeApiClientImplTest.java @@ -244,7 +244,7 @@ public void reportInvocationErrorTest() { mockWebServer.enqueue(mockResponse); LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType); - lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError); + lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null); RecordedRequest recordedRequest = mockWebServer.takeRequest(); HttpUrl actualUrl = recordedRequest.getRequestUrl(); String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error"; @@ -274,7 +274,7 @@ public void reportInvocationErrorTestWrongStatusCode() { mockWebServer.enqueue(mockResponse); LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType); - lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError); + lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null); fail(); } catch(LambdaRuntimeClientException e) { String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/error"; @@ -318,7 +318,7 @@ public void reportLambdaErrorWithXRayTest() { XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths); LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType); - lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError); + lambdaRuntimeApiClientImpl.reportInvocationError(requestId, lambdaError, null); RecordedRequest recordedRequest = mockWebServer.takeRequest(); String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause"); @@ -339,7 +339,7 @@ public void reportInvocationSuccessTest() { mockWebServer.enqueue(mockResponse); String response = "{\"msg\":\"test\"}"; - lambdaRuntimeApiClientImpl.reportInvocationSuccess(requestId, response.getBytes()); + lambdaRuntimeApiClientImpl.reportInvocationSuccess(requestId, response.getBytes(), null); RecordedRequest recordedRequest = mockWebServer.takeRequest(); HttpUrl actualUrl = recordedRequest.getRequestUrl(); String expectedUrl = "http://" + getHostnamePort() + "/2018-06-01/runtime/invocation/1234/response"; @@ -456,7 +456,7 @@ public void createUrlMalformedTest() { RapidErrorType rapidErrorType = RapidErrorType.AfterRestoreError; LambdaError lambdaError = new LambdaError(errorRequest, rapidErrorType); RuntimeException thrown = assertThrows(RuntimeException.class, ()->{ - lambdaRuntimeApiClientImpl.reportLambdaError("invalidurl", lambdaError, 100); + lambdaRuntimeApiClientImpl.reportLambdaError("invalidurl", lambdaError, 100, null); }); assertTrue(thrown.getLocalizedMessage().contains("java.net.MalformedURLException")); } @@ -483,7 +483,7 @@ public void lambdaReportErrorXRayHeaderTooLongTest() { XRayErrorCause xRayErrorCause = new XRayErrorCause(workingDirectory, exceptions, paths); LambdaError lambdaError = new LambdaError(errorRequest, xRayErrorCause, rapidErrorType); - lambdaRuntimeApiClientImpl.reportLambdaError("http://" + getHostnamePort(), lambdaError, 10); + lambdaRuntimeApiClientImpl.reportLambdaError("http://" + getHostnamePort(), lambdaError, 10, null); RecordedRequest recordedRequest = mockWebServer.takeRequest(); String xrayErrorCauseHeader = recordedRequest.getHeader("Lambda-Runtime-Function-XRay-Error-Cause");