Skip to content

Commit b8d89ca

Browse files
authored
Add ControlPlaneRequest, ControlPlaneResponse (#238)
### Motivation: In the coming weeks, we want to restructure the LambdaRuntime internals in such a way, that we allocate a lot less resources per invocation. To accomplish this, we want to encode and decode the ControlPlaneAPI requests directly from their semantic value. For this reason, we need a specialized ControlPlaneRequest and ControlPlaneResponse type that we can encode from and decode into. ### Modifications: - Add `ControlPlaneRequest`, `ControlPlaneResponse` - Move `Invocation` and `ErrorResponse` into same file as `ControlPlaneRequest` - Remove `Lambda` namespace around `Invocation`
1 parent 4317c53 commit b8d89ca

File tree

4 files changed

+88
-61
lines changed

4 files changed

+88
-61
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2017-2021 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import NIOCore
16+
import NIOHTTP1
17+
18+
enum ControlPlaneRequest: Hashable {
19+
case next
20+
case invocationResponse(String, ByteBuffer?)
21+
case invocationError(String, ErrorResponse)
22+
case initializationError(ErrorResponse)
23+
}
24+
25+
enum ControlPlaneResponse: Hashable {
26+
case next(Invocation, ByteBuffer)
27+
case accepted
28+
case error(ErrorResponse)
29+
}
30+
31+
struct Invocation: Hashable {
32+
let requestID: String
33+
let deadlineInMillisSinceEpoch: Int64
34+
let invokedFunctionARN: String
35+
let traceID: String
36+
let clientContext: String?
37+
let cognitoIdentity: String?
38+
39+
init(headers: HTTPHeaders) throws {
40+
guard let requestID = headers.first(name: AmazonHeaders.requestID), !requestID.isEmpty else {
41+
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.requestID)
42+
}
43+
44+
guard let deadline = headers.first(name: AmazonHeaders.deadline),
45+
let unixTimeInMilliseconds = Int64(deadline)
46+
else {
47+
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.deadline)
48+
}
49+
50+
guard let invokedFunctionARN = headers.first(name: AmazonHeaders.invokedFunctionARN) else {
51+
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.invokedFunctionARN)
52+
}
53+
54+
guard let traceID = headers.first(name: AmazonHeaders.traceID) else {
55+
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.traceID)
56+
}
57+
58+
self.requestID = requestID
59+
self.deadlineInMillisSinceEpoch = unixTimeInMilliseconds
60+
self.invokedFunctionARN = invokedFunctionARN
61+
self.traceID = traceID
62+
self.clientContext = headers["Lambda-Runtime-Client-Context"].first
63+
self.cognitoIdentity = headers["Lambda-Runtime-Cognito-Identity"].first
64+
}
65+
}
66+
67+
struct ErrorResponse: Hashable, Codable {
68+
var errorType: String
69+
var errorMessage: String
70+
}
71+
72+
extension ErrorResponse {
73+
internal func toJSONBytes() -> [UInt8] {
74+
var bytes = [UInt8]()
75+
bytes.append(UInt8(ascii: "{"))
76+
bytes.append(contentsOf: #""errorType":"#.utf8)
77+
self.errorType.encodeAsJSONString(into: &bytes)
78+
bytes.append(contentsOf: #","errorMessage":"#.utf8)
79+
self.errorMessage.encodeAsJSONString(into: &bytes)
80+
bytes.append(UInt8(ascii: "}"))
81+
return bytes
82+
}
83+
}

Sources/AWSLambdaRuntimeCore/LambdaRunner.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ extension Lambda {
103103
}
104104

105105
extension LambdaContext {
106-
init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Lambda.Invocation) {
106+
init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Invocation) {
107107
self.init(requestID: invocation.requestID,
108108
traceID: invocation.traceID,
109109
invokedFunctionARN: invocation.invokedFunctionARN,

Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift

-56
Original file line numberDiff line numberDiff line change
@@ -137,62 +137,6 @@ extension Lambda {
137137
}
138138
}
139139

140-
internal struct ErrorResponse: Codable {
141-
var errorType: String
142-
var errorMessage: String
143-
}
144-
145-
extension ErrorResponse {
146-
internal func toJSONBytes() -> [UInt8] {
147-
var bytes = [UInt8]()
148-
bytes.append(UInt8(ascii: "{"))
149-
bytes.append(contentsOf: #""errorType":"#.utf8)
150-
self.errorType.encodeAsJSONString(into: &bytes)
151-
bytes.append(contentsOf: #","errorMessage":"#.utf8)
152-
self.errorMessage.encodeAsJSONString(into: &bytes)
153-
bytes.append(UInt8(ascii: "}"))
154-
return bytes
155-
}
156-
}
157-
158-
extension Lambda {
159-
internal struct Invocation {
160-
let requestID: String
161-
let deadlineInMillisSinceEpoch: Int64
162-
let invokedFunctionARN: String
163-
let traceID: String
164-
let clientContext: String?
165-
let cognitoIdentity: String?
166-
167-
init(headers: HTTPHeaders) throws {
168-
guard let requestID = headers.first(name: AmazonHeaders.requestID), !requestID.isEmpty else {
169-
throw RuntimeError.invocationMissingHeader(AmazonHeaders.requestID)
170-
}
171-
172-
guard let deadline = headers.first(name: AmazonHeaders.deadline),
173-
let unixTimeInMilliseconds = Int64(deadline)
174-
else {
175-
throw RuntimeError.invocationMissingHeader(AmazonHeaders.deadline)
176-
}
177-
178-
guard let invokedFunctionARN = headers.first(name: AmazonHeaders.invokedFunctionARN) else {
179-
throw RuntimeError.invocationMissingHeader(AmazonHeaders.invokedFunctionARN)
180-
}
181-
182-
guard let traceID = headers.first(name: AmazonHeaders.traceID) else {
183-
throw RuntimeError.invocationMissingHeader(AmazonHeaders.traceID)
184-
}
185-
186-
self.requestID = requestID
187-
self.deadlineInMillisSinceEpoch = unixTimeInMilliseconds
188-
self.invokedFunctionARN = invokedFunctionARN
189-
self.traceID = traceID
190-
self.clientContext = headers["Lambda-Runtime-Client-Context"].first
191-
self.cognitoIdentity = headers["Lambda-Runtime-Cognito-Identity"].first
192-
}
193-
}
194-
}
195-
196140
extension Lambda.RuntimeClient {
197141
internal static let defaultHeaders = HTTPHeaders([("user-agent", "Swift-Lambda/Unknown")])
198142

Tests/AWSLambdaRuntimeCoreTests/LambdaRuntimeClientTest.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -260,8 +260,8 @@ class LambdaRuntimeClientTest: XCTestCase {
260260
(AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
261261
(AmazonHeaders.traceID, "Root=\(AmazonHeaders.generateXRayTraceID());Sampled=1"),
262262
])
263-
var inv: Lambda.Invocation?
264-
XCTAssertNoThrow(inv = try Lambda.Invocation(headers: header))
263+
var inv: Invocation?
264+
XCTAssertNoThrow(inv = try Invocation(headers: header))
265265
guard let invocation = inv else { return }
266266

267267
let result = client.reportResults(logger: logger, invocation: invocation, result: Result.failure(TestError("boom")))
@@ -300,8 +300,8 @@ class LambdaRuntimeClientTest: XCTestCase {
300300
(AmazonHeaders.invokedFunctionARN, "arn:aws:lambda:us-east-1:123456789012:function:custom-runtime"),
301301
(AmazonHeaders.traceID, "Root=\(AmazonHeaders.generateXRayTraceID());Sampled=1"),
302302
])
303-
var inv: Lambda.Invocation?
304-
XCTAssertNoThrow(inv = try Lambda.Invocation(headers: header))
303+
var inv: Invocation?
304+
XCTAssertNoThrow(inv = try Invocation(headers: header))
305305
guard let invocation = inv else { return }
306306

307307
let result = client.reportResults(logger: logger, invocation: invocation, result: Result.success(nil))

0 commit comments

Comments
 (0)