From a70a396cf3dc66b2496da21437ef256264cdd9a4 Mon Sep 17 00:00:00 2001
From: Aryan Shah <aryan_shah@apple.com>
Date: Wed, 28 Aug 2024 10:55:29 +0100
Subject: [PATCH 1/3] Add LambdaRuntimeClientProtocol

---
 .../ControlPlaneRequest.swift                 | 18 +++++-----
 .../LambdaRuntimeClient.swift                 |  4 +--
 .../LambdaRuntimeClientProtocol.swift         | 33 +++++++++++++++++++
 .../ControlPlaneRequestTests.swift            |  4 +--
 .../LambdaRuntimeClientTest.swift             |  8 ++---
 5 files changed, 50 insertions(+), 17 deletions(-)
 create mode 100644 Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift

diff --git a/Sources/AWSLambdaRuntimeCore/ControlPlaneRequest.swift b/Sources/AWSLambdaRuntimeCore/ControlPlaneRequest.swift
index 6c29344c..da3d41d2 100644
--- a/Sources/AWSLambdaRuntimeCore/ControlPlaneRequest.swift
+++ b/Sources/AWSLambdaRuntimeCore/ControlPlaneRequest.swift
@@ -23,20 +23,20 @@ enum ControlPlaneRequest: Hashable {
 }
 
 enum ControlPlaneResponse: Hashable {
-    case next(Invocation, ByteBuffer)
+    case next(InvocationMetadata, ByteBuffer)
     case accepted
     case error(ErrorResponse)
 }
 
-struct Invocation: Hashable {
-    let requestID: String
-    let deadlineInMillisSinceEpoch: Int64
-    let invokedFunctionARN: String
-    let traceID: String
-    let clientContext: String?
-    let cognitoIdentity: String?
+package struct InvocationMetadata: Hashable {
+    package let requestID: String
+    package let deadlineInMillisSinceEpoch: Int64
+    package let invokedFunctionARN: String
+    package let traceID: String
+    package let clientContext: String?
+    package let cognitoIdentity: String?
 
-    init(headers: HTTPHeaders) throws {
+    package init(headers: HTTPHeaders) throws {
         guard let requestID = headers.first(name: AmazonHeaders.requestID), !requestID.isEmpty else {
             throw LambdaRuntimeError.invocationMissingHeader(AmazonHeaders.requestID)
         }
diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
index 6836e42e..4abab384 100644
--- a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
+++ b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
@@ -32,14 +32,14 @@ struct LambdaRuntimeClient {
     }
 
     /// Requests invocation from the control plane.
-    func getNextInvocation(logger: Logger) -> EventLoopFuture<(Invocation, ByteBuffer)> {
+    func getNextInvocation(logger: Logger) -> EventLoopFuture<(InvocationMetadata, ByteBuffer)> {
         let url = Consts.invocationURLPrefix + Consts.getNextInvocationURLSuffix
         logger.debug("requesting work from lambda runtime engine using \(url)")
         return self.httpClient.get(url: url, headers: LambdaRuntimeClient.defaultHeaders).flatMapThrowing { response in
             guard response.status == .ok else {
                 throw LambdaRuntimeError.badStatusCode(response.status)
             }
-            let invocation = try Invocation(headers: response.headers)
+            let invocation = try InvocationMetadata(headers: response.headers)
             guard let event = response.body else {
                 throw LambdaRuntimeError.noBody
             }
diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift
new file mode 100644
index 00000000..30ea818b
--- /dev/null
+++ b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the SwiftAWSLambdaRuntime open source project
+//
+// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors
+// Licensed under Apache License v2.0
+//
+// See LICENSE.txt for license information
+// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
+//
+// SPDX-License-Identifier: Apache-2.0
+//
+//===----------------------------------------------------------------------===//
+
+import NIOCore
+
+package protocol LambdaResponseStreamWriter {
+    mutating func write(_ buffer: ByteBuffer) async throws
+    func finish() async throws
+    func writeAndFinish(_ buffer: ByteBuffer) async throws
+    func reportError(_ error: any Error) async throws
+}
+
+package protocol LambdaRuntimeClientProtocol {
+    associatedtype Writer: LambdaResponseStreamWriter
+
+    func nextInvocation() async throws -> (Invocation, Writer)
+}
+
+package struct Invocation {
+    package let metadata: InvocationMetadata
+    package let event: ByteBuffer
+}
diff --git a/Tests/AWSLambdaRuntimeCoreTests/ControlPlaneRequestTests.swift b/Tests/AWSLambdaRuntimeCoreTests/ControlPlaneRequestTests.swift
index a52446c8..013cf9d8 100644
--- a/Tests/AWSLambdaRuntimeCoreTests/ControlPlaneRequestTests.swift
+++ b/Tests/AWSLambdaRuntimeCoreTests/ControlPlaneRequestTests.swift
@@ -25,9 +25,9 @@ class InvocationTest: XCTestCase {
             (AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
         ])
 
-        var invocation: Invocation?
+        var invocation: InvocationMetadata?
 
-        XCTAssertNoThrow(invocation = try Invocation(headers: headers))
+        XCTAssertNoThrow(invocation = try InvocationMetadata(headers: headers))
         XCTAssertNotNil(invocation)
 
         guard !invocation!.traceID.isEmpty else {
diff --git a/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeClientTest.swift b/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeClientTest.swift
index 01d7cafb..749f1c64 100644
--- a/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeClientTest.swift
+++ b/Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeClientTest.swift
@@ -279,8 +279,8 @@ class LambdaRuntimeClientTest: XCTestCase {
             (AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
             (AmazonHeaders.traceID, "Root=\(AmazonHeaders.generateXRayTraceID());Sampled=1"),
         ])
-        var inv: Invocation?
-        XCTAssertNoThrow(inv = try Invocation(headers: header))
+        var inv: InvocationMetadata?
+        XCTAssertNoThrow(inv = try InvocationMetadata(headers: header))
         guard let invocation = inv else { return }
 
         let result = client.reportResults(
@@ -332,8 +332,8 @@ class LambdaRuntimeClientTest: XCTestCase {
             (AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
             (AmazonHeaders.traceID, "Root=\(AmazonHeaders.generateXRayTraceID());Sampled=1"),
         ])
-        var inv: Invocation?
-        XCTAssertNoThrow(inv = try Invocation(headers: header))
+        var inv: InvocationMetadata?
+        XCTAssertNoThrow(inv = try InvocationMetadata(headers: header))
         guard let invocation = inv else { return }
 
         let result = client.reportResults(logger: logger, invocation: invocation, result: Result.success(nil))

From 445402fc9ea1297564406caffdffd5563dbb3c5c Mon Sep 17 00:00:00 2001
From: Aryan Shah <aryan_shah@apple.com>
Date: Wed, 28 Aug 2024 12:15:13 +0100
Subject: [PATCH 2/3] Fix rename

---
 Sources/AWSLambdaRuntimeCore/LambdaRunner.swift        | 2 +-
 Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift
index b7c1683a..6ecafa5a 100644
--- a/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift
+++ b/Sources/AWSLambdaRuntimeCore/LambdaRunner.swift
@@ -132,7 +132,7 @@ final class LambdaRunner {
 }
 
 extension LambdaContext {
-    init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Invocation) {
+    init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: InvocationMetadata) {
         self.init(
             requestID: invocation.requestID,
             traceID: invocation.traceID,
diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
index 4abab384..36f88229 100644
--- a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
+++ b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift
@@ -59,7 +59,7 @@ struct LambdaRuntimeClient {
     /// Reports a result to the Runtime Engine.
     func reportResults(
         logger: Logger,
-        invocation: Invocation,
+        invocation: InvocationMetadata,
         result: Result<ByteBuffer?, Error>
     ) -> EventLoopFuture<Void> {
         var url = Consts.invocationURLPrefix + "/" + invocation.requestID

From 9a681717266e312de2d8d84c72a2bb4adb8f2fbb Mon Sep 17 00:00:00 2001
From: Aryan Shah <aryan_shah@apple.com>
Date: Wed, 28 Aug 2024 12:16:05 +0100
Subject: [PATCH 3/3] Invocation: Replace let with var and add initializer

---
 .../LambdaRuntimeClientProtocol.swift                    | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift
index 30ea818b..f85b1b4f 100644
--- a/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift
+++ b/Sources/AWSLambdaRuntimeCore/LambdaRuntimeClientProtocol.swift
@@ -28,6 +28,11 @@ package protocol LambdaRuntimeClientProtocol {
 }
 
 package struct Invocation {
-    package let metadata: InvocationMetadata
-    package let event: ByteBuffer
+    package var metadata: InvocationMetadata
+    package var event: ByteBuffer
+
+    package init(metadata: InvocationMetadata, event: ByteBuffer) {
+        self.metadata = metadata
+        self.event = event
+    }
 }