mirror of
https://github.com/swift-server/swift-aws-lambda-runtime.git
synced 2026-06-02 07:27:33 +00:00
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`
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This source file is part of the SwiftAWSLambdaRuntime open source project
|
||||
//
|
||||
// Copyright (c) 2017-2021 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
|
||||
import NIOHTTP1
|
||||
|
||||
enum ControlPlaneRequest: Hashable {
|
||||
case next
|
||||
case invocationResponse(String, ByteBuffer?)
|
||||
case invocationError(String, ErrorResponse)
|
||||
case initializationError(ErrorResponse)
|
||||
}
|
||||
|
||||
enum ControlPlaneResponse: Hashable {
|
||||
case next(Invocation, 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?
|
||||
|
||||
init(headers: HTTPHeaders) throws {
|
||||
guard let requestID = headers.first(name: AmazonHeaders.requestID), !requestID.isEmpty else {
|
||||
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.requestID)
|
||||
}
|
||||
|
||||
guard let deadline = headers.first(name: AmazonHeaders.deadline),
|
||||
let unixTimeInMilliseconds = Int64(deadline)
|
||||
else {
|
||||
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.deadline)
|
||||
}
|
||||
|
||||
guard let invokedFunctionARN = headers.first(name: AmazonHeaders.invokedFunctionARN) else {
|
||||
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.invokedFunctionARN)
|
||||
}
|
||||
|
||||
guard let traceID = headers.first(name: AmazonHeaders.traceID) else {
|
||||
throw Lambda.RuntimeError.invocationMissingHeader(AmazonHeaders.traceID)
|
||||
}
|
||||
|
||||
self.requestID = requestID
|
||||
self.deadlineInMillisSinceEpoch = unixTimeInMilliseconds
|
||||
self.invokedFunctionARN = invokedFunctionARN
|
||||
self.traceID = traceID
|
||||
self.clientContext = headers["Lambda-Runtime-Client-Context"].first
|
||||
self.cognitoIdentity = headers["Lambda-Runtime-Cognito-Identity"].first
|
||||
}
|
||||
}
|
||||
|
||||
struct ErrorResponse: Hashable, Codable {
|
||||
var errorType: String
|
||||
var errorMessage: String
|
||||
}
|
||||
|
||||
extension ErrorResponse {
|
||||
internal func toJSONBytes() -> [UInt8] {
|
||||
var bytes = [UInt8]()
|
||||
bytes.append(UInt8(ascii: "{"))
|
||||
bytes.append(contentsOf: #""errorType":"#.utf8)
|
||||
self.errorType.encodeAsJSONString(into: &bytes)
|
||||
bytes.append(contentsOf: #","errorMessage":"#.utf8)
|
||||
self.errorMessage.encodeAsJSONString(into: &bytes)
|
||||
bytes.append(UInt8(ascii: "}"))
|
||||
return bytes
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ extension Lambda {
|
||||
}
|
||||
|
||||
extension LambdaContext {
|
||||
init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Lambda.Invocation) {
|
||||
init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Invocation) {
|
||||
self.init(requestID: invocation.requestID,
|
||||
traceID: invocation.traceID,
|
||||
invokedFunctionARN: invocation.invokedFunctionARN,
|
||||
|
||||
@@ -137,62 +137,6 @@ extension Lambda {
|
||||
}
|
||||
}
|
||||
|
||||
internal struct ErrorResponse: Codable {
|
||||
var errorType: String
|
||||
var errorMessage: String
|
||||
}
|
||||
|
||||
extension ErrorResponse {
|
||||
internal func toJSONBytes() -> [UInt8] {
|
||||
var bytes = [UInt8]()
|
||||
bytes.append(UInt8(ascii: "{"))
|
||||
bytes.append(contentsOf: #""errorType":"#.utf8)
|
||||
self.errorType.encodeAsJSONString(into: &bytes)
|
||||
bytes.append(contentsOf: #","errorMessage":"#.utf8)
|
||||
self.errorMessage.encodeAsJSONString(into: &bytes)
|
||||
bytes.append(UInt8(ascii: "}"))
|
||||
return bytes
|
||||
}
|
||||
}
|
||||
|
||||
extension Lambda {
|
||||
internal struct Invocation {
|
||||
let requestID: String
|
||||
let deadlineInMillisSinceEpoch: Int64
|
||||
let invokedFunctionARN: String
|
||||
let traceID: String
|
||||
let clientContext: String?
|
||||
let cognitoIdentity: String?
|
||||
|
||||
init(headers: HTTPHeaders) throws {
|
||||
guard let requestID = headers.first(name: AmazonHeaders.requestID), !requestID.isEmpty else {
|
||||
throw RuntimeError.invocationMissingHeader(AmazonHeaders.requestID)
|
||||
}
|
||||
|
||||
guard let deadline = headers.first(name: AmazonHeaders.deadline),
|
||||
let unixTimeInMilliseconds = Int64(deadline)
|
||||
else {
|
||||
throw RuntimeError.invocationMissingHeader(AmazonHeaders.deadline)
|
||||
}
|
||||
|
||||
guard let invokedFunctionARN = headers.first(name: AmazonHeaders.invokedFunctionARN) else {
|
||||
throw RuntimeError.invocationMissingHeader(AmazonHeaders.invokedFunctionARN)
|
||||
}
|
||||
|
||||
guard let traceID = headers.first(name: AmazonHeaders.traceID) else {
|
||||
throw RuntimeError.invocationMissingHeader(AmazonHeaders.traceID)
|
||||
}
|
||||
|
||||
self.requestID = requestID
|
||||
self.deadlineInMillisSinceEpoch = unixTimeInMilliseconds
|
||||
self.invokedFunctionARN = invokedFunctionARN
|
||||
self.traceID = traceID
|
||||
self.clientContext = headers["Lambda-Runtime-Client-Context"].first
|
||||
self.cognitoIdentity = headers["Lambda-Runtime-Cognito-Identity"].first
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Lambda.RuntimeClient {
|
||||
internal static let defaultHeaders = HTTPHeaders([("user-agent", "Swift-Lambda/Unknown")])
|
||||
|
||||
|
||||
@@ -260,8 +260,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: Lambda.Invocation?
|
||||
XCTAssertNoThrow(inv = try Lambda.Invocation(headers: header))
|
||||
var inv: Invocation?
|
||||
XCTAssertNoThrow(inv = try Invocation(headers: header))
|
||||
guard let invocation = inv else { return }
|
||||
|
||||
let result = client.reportResults(logger: logger, invocation: invocation, result: Result.failure(TestError("boom")))
|
||||
@@ -300,8 +300,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: Lambda.Invocation?
|
||||
XCTAssertNoThrow(inv = try Lambda.Invocation(headers: header))
|
||||
var inv: Invocation?
|
||||
XCTAssertNoThrow(inv = try Invocation(headers: header))
|
||||
guard let invocation = inv else { return }
|
||||
|
||||
let result = client.reportResults(logger: logger, invocation: invocation, result: Result.success(nil))
|
||||
|
||||
Reference in New Issue
Block a user