Skip to content

Commit d4c99c7

Browse files
committed
make more Swift-like
1 parent 377e2ba commit d4c99c7

12 files changed

+127
-173
lines changed

Sources/SwiftAwsLambda/Lambda+Codable.swift

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ extension Lambda {
3434
}
3535
}
3636

37-
public enum LambdaCodableResult<Out> {
38-
case success(Out)
39-
case failure(String)
40-
}
37+
public typealias LambdaCodableResult<Out> = LambdaResult<Out, String>
4138

4239
public typealias LambdaCodableCallback<Out> = (LambdaCodableResult<Out>) -> Void
4340

@@ -65,7 +62,7 @@ public class LambdaCodableCodec<In: Decodable, Out: Encodable> {
6562
}
6663

6764
public extension LambdaCodableHandler {
68-
func handle(context: LambdaContext, payload: [UInt8], callback: @escaping (LambdaResult) -> Void) {
65+
func handle(context: LambdaContext, payload: [UInt8], callback: @escaping (LambdaResult<[UInt8], String>) -> Void) {
6966
guard let payloadAsCodable = codec.decode(payload) else {
7067
return callback(.failure("failed decoding payload (in)"))
7168
}

Sources/SwiftAwsLambda/Lambda+String.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,7 @@ extension Lambda {
3232
}
3333
}
3434

35-
public enum LambdaStringResult {
36-
case success(String)
37-
case failure(String)
38-
}
39-
35+
public typealias LambdaStringResult = LambdaResult<String, String>
4036
public typealias LambdaStringCallback = (LambdaStringResult) -> Void
4137

4238
public typealias LambdaStringClosure = (LambdaContext, String, LambdaStringCallback) -> Void

Sources/SwiftAwsLambda/Lambda.swift

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -66,17 +66,14 @@ public final class Lambda {
6666
}
6767
}
6868

69-
public enum LambdaLifecycleResult {
70-
case success(Int)
69+
public enum LambdaResult<Value, Error> {
70+
case success(Value)
7171
case failure(Error)
7272
}
7373

74-
public enum LambdaResult {
75-
case success([UInt8])
76-
case failure(String)
77-
}
74+
public typealias LambdaLifecycleResult = LambdaResult<Int, Error>
7875

79-
public typealias LambdaCallback = (LambdaResult) -> Void
76+
public typealias LambdaCallback = (LambdaResult<[UInt8], String>) -> Void
8077

8178
public typealias LambdaClosure = (LambdaContext, [UInt8], LambdaCallback) -> Void
8279

Sources/SwiftAwsLambda/LambdaRunner.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ internal final class LambdaRunner {
3939
case let .success(context, payload):
4040
// 2. send work to handler
4141
print("sending work to lambda handler \(self.lambdaHandler)")
42-
let promise: EventLoopPromise<LambdaResult> = self.eventLoop.newPromise()
42+
let promise: EventLoopPromise<LambdaResult<[UInt8], String>> = self.eventLoop.newPromise()
4343
self.lambdaHandler.handle(context: context, payload: payload, promise: promise)
4444
return promise.futureResult.then { lambdaResult in
4545
// 3. report results to runtime engine
@@ -51,7 +51,7 @@ internal final class LambdaRunner {
5151
case .success():
5252
// we are done!
5353
print("lambda invocation sequence completed successfully")
54-
return self.newSucceededFuture(result: .success())
54+
return self.newSucceededFuture(result: .success(()))
5555
}
5656
}
5757
}
@@ -64,16 +64,13 @@ internal final class LambdaRunner {
6464
}
6565
}
6666

67-
internal enum RunLambdaResult {
68-
case success()
69-
case failure(Error)
70-
}
67+
internal typealias RunLambdaResult = LambdaResult<(), Error>
7168

7269
private extension LambdaHandler {
73-
func handle(context: LambdaContext, payload: [UInt8], promise: EventLoopPromise<LambdaResult>) {
70+
func handle(context: LambdaContext, payload: [UInt8], promise: EventLoopPromise<LambdaResult<[UInt8], String>>) {
7471
// offloading so user code never blocks the eventloop
7572
DispatchQueue(label: "lambda-\(context.requestId)").async {
76-
self.handle(context: context, payload: payload, callback: { (result: LambdaResult) in
73+
self.handle(context: context, payload: payload, callback: { (result: LambdaResult<[UInt8], String>) in
7774
promise.succeed(result: result)
7875
})
7976
}

Sources/SwiftAwsLambda/LambdaRuntimeClient.swift

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ internal class LambdaRuntimeClient {
2929
}
3030

3131
func requestWork() -> EventLoopFuture<RequestWorkResult> {
32-
let url = baseUrl + Consts.InvokationUrlPrefix + Consts.RequestWorkUrlSuffix
32+
let url = baseUrl + Consts.invokationURLPrefix + Consts.requestWorkURLSuffix
3333
print("requesting work from lambda runtime engine using \(url)")
3434
return httpClient.get(url: url).map { response in
3535
if .ok != response.status {
@@ -38,23 +38,23 @@ internal class LambdaRuntimeClient {
3838
guard let payload = response.readWholeBody() else {
3939
return .failure(.noBody)
4040
}
41-
guard let context = LambdaContext.from(response) else {
41+
guard let context = LambdaContext(response: response) else {
4242
return .failure(.noContext)
4343
}
44-
return .success(context: context, payload: payload)
44+
return .success((context, payload))
4545
}
4646
}
4747

48-
func reportResults(context: LambdaContext, result: LambdaResult) -> EventLoopFuture<PostResultsResult> {
49-
var url = baseUrl + Consts.InvokationUrlPrefix + "/" + context.requestId
48+
func reportResults(context: LambdaContext, result: LambdaResult<[UInt8], String>) -> EventLoopFuture<PostResultsResult> {
49+
var url = baseUrl + Consts.invokationURLPrefix + "/" + context.requestId
5050
var body: ByteBuffer
5151
switch result {
5252
case let .success(data):
53-
url += Consts.PostResponseUrlSuffix
53+
url += Consts.postResponseURLSuffix
5454
body = allocator.buffer(capacity: data.count)
5555
body.write(bytes: data)
5656
case let .failure(error):
57-
url += Consts.PostErrorUrlSuffix
57+
url += Consts.postErrorURLSuffix
5858
// TODO: make FunctionError a const
5959
// FIXME: error
6060
let error = ErrorResponse(errorType: "FunctionError", errorMessage: "\(error)")
@@ -67,20 +67,13 @@ internal class LambdaRuntimeClient {
6767

6868
print("reporting results to lambda runtime engine using \(url)")
6969
return httpClient.post(url: url, body: body).map { response in
70-
.accepted != response.status ? .failure(.badStatusCode) : .success()
70+
.accepted != response.status ? .failure(.badStatusCode) : .success(())
7171
}
7272
}
7373
}
7474

75-
internal enum RequestWorkResult {
76-
case success(context: LambdaContext, payload: [UInt8])
77-
case failure(LambdaRuntimeClientError)
78-
}
79-
80-
internal enum PostResultsResult {
81-
case success()
82-
case failure(LambdaRuntimeClientError)
83-
}
75+
internal typealias RequestWorkResult = LambdaResult<(LambdaContext, [UInt8]), LambdaRuntimeClientError>
76+
internal typealias PostResultsResult = LambdaResult<(), LambdaRuntimeClientError>
8477

8578
internal enum LambdaRuntimeClientError: Error {
8679
case badStatusCode
@@ -107,8 +100,8 @@ private extension ErrorResponse {
107100
}
108101

109102
private extension HTTPResponse {
110-
func getHeaderValue(_ name: String) -> String? {
111-
return headers[name][safe: 0]
103+
func headerValue(_ name: String) -> String? {
104+
return headers[name].first
112105
}
113106

114107
func readWholeBody() -> [UInt8]? {
@@ -123,19 +116,19 @@ private extension HTTPResponse {
123116
}
124117

125118
private extension LambdaContext {
126-
static func from(_ response: HTTPResponse) -> LambdaContext? {
127-
guard let requestId = response.getHeaderValue(AmazonHeaders.RequestId) else {
119+
init?(response: HTTPResponse) {
120+
guard let requestId = response.headerValue(AmazonHeaders.requestID) else {
128121
return nil
129122
}
130123
if requestId.isEmpty {
131124
return nil
132125
}
133-
let traceId = response.getHeaderValue(AmazonHeaders.TraceId)
134-
let invokedFunctionArn = response.getHeaderValue(AmazonHeaders.InvokedFunctionArn)
135-
let cognitoIdentity = response.getHeaderValue(AmazonHeaders.CognitoIdentity)
136-
let clientContext = response.getHeaderValue(AmazonHeaders.ClientContext)
137-
let deadlineNs = response.getHeaderValue(AmazonHeaders.DeadlineNs)
138-
return LambdaContext(requestId: requestId,
126+
let traceId = response.headerValue(AmazonHeaders.traceID)
127+
let invokedFunctionArn = response.headerValue(AmazonHeaders.invokedFunctionARN)
128+
let cognitoIdentity = response.headerValue(AmazonHeaders.cognitoIdentity)
129+
let clientContext = response.headerValue(AmazonHeaders.clientContext)
130+
let deadlineNs = response.headerValue(AmazonHeaders.deadlineNS)
131+
self = LambdaContext(requestId: requestId,
139132
traceId: traceId,
140133
invokedFunctionArn: invokedFunctionArn,
141134
cognitoIdentity: cognitoIdentity,
@@ -145,9 +138,9 @@ private extension LambdaContext {
145138
}
146139

147140
private func getRuntimeEndpoint() -> String {
148-
if let hostPort = Environment.getString(Consts.HostPortEnvVariableName) {
141+
if let hostPort = Environment.string(Consts.hostPortEnvVariableName) {
149142
return "http://\(hostPort)"
150143
} else {
151-
return "http://\(Defaults.Host):\(Defaults.Port)"
144+
return "http://\(Defaults.host):\(Defaults.port)"
152145
}
153146
}

Sources/SwiftAwsLambda/Utils.swift

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,55 +14,49 @@
1414

1515
import NIO
1616

17-
internal final class Consts {
18-
static let HostPortEnvVariableName = "AWS_LAMBDA_RUNTIME_API"
17+
internal enum Consts {
18+
static let hostPortEnvVariableName = "AWS_LAMBDA_RUNTIME_API"
1919

20-
static let InvokationUrlPrefix = "/RUNTIME/INVOCATION"
21-
static let RequestWorkUrlSuffix = "/NEXT"
22-
static let PostResponseUrlSuffix = "/RESPONSE"
23-
static let PostErrorUrlSuffix = "/ERROR"
20+
static let invokationURLPrefix = "/RUNTIME/INVOCATION"
21+
static let requestWorkURLSuffix = "/NEXT"
22+
static let postResponseURLSuffix = "/RESPONSE"
23+
static let postErrorURLSuffix = "/ERROR"
2424
}
2525

26-
internal final class AmazonHeaders {
27-
static let RequestId = "X-Amz-Aws-Request-Id"
28-
static let TraceId = "X-Amz-Trace-Id"
29-
static let ClientContext = "X-Amz-Client-Context"
30-
static let CognitoIdentity = "X-Amz-Cognito-Identity"
31-
static let DeadlineNs = "X-Amz-Deadline-Ns"
32-
static let InvokedFunctionArn = "X-Amz-Invoked-Function-Arn"
26+
internal enum AmazonHeaders {
27+
static let requestID = "X-Amz-Aws-Request-Id"
28+
static let traceID = "X-Amz-Trace-Id"
29+
static let clientContext = "X-Amz-Client-Context"
30+
static let cognitoIdentity = "X-Amz-Cognito-Identity"
31+
static let deadlineNS = "X-Amz-Deadline-Ns"
32+
static let invokedFunctionARN = "X-Amz-Invoked-Function-Arn"
3333
}
3434

35-
internal final class Defaults {
36-
static let Host = "127.0.0.1"
37-
static let Port = 8080
35+
internal enum Defaults {
36+
static let host = "127.0.0.1"
37+
static let port = 8080
3838
}
3939

40-
internal final class Environment {
41-
class func getString(name: String, defaultValue: String) -> String {
42-
return getString(name) ?? defaultValue
40+
internal enum Environment {
41+
static func string(name: String, defaultValue: String) -> String {
42+
return string(name) ?? defaultValue
4343
}
4444

45-
class func getString(_ name: String) -> String? {
45+
static func string(_ name: String) -> String? {
4646
guard let value = getenv(name) else {
4747
return nil
4848
}
4949
return String(validatingUTF8: value)
5050
}
5151

52-
class func getInt(name: String, defaultValue: Int) -> Int {
53-
return getInt(name) ?? defaultValue
52+
static func int(name: String, defaultValue: Int) -> Int {
53+
return int(name) ?? defaultValue
5454
}
5555

56-
class func getInt(_ name: String) -> Int? {
57-
guard let value = getString(name) else {
56+
static func int(_ name: String) -> Int? {
57+
guard let value = string(name) else {
5858
return nil
5959
}
6060
return Int(value)
6161
}
6262
}
63-
64-
internal extension Collection {
65-
subscript(safe index: Index) -> Element? {
66-
return indices.contains(index) ? self[index] : nil
67-
}
68-
}

Tests/SwiftAwsLambdaTests/Lambda+CodeableTest.swift

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,45 +77,45 @@ private class GoodBehavior: LambdaServerBehavior {
7777
func getWork() -> GetWorkResult {
7878
guard let payload = try? JSONEncoder().encode(Req(requestId: requestId)) else {
7979
XCTFail("encoding error")
80-
return .failure(.InternalServerError)
80+
return .failure(.internalServerError)
8181
}
8282
guard let payloadAsString = String(data: payload, encoding: .utf8) else {
8383
XCTFail("encoding error")
84-
return .failure(.InternalServerError)
84+
return .failure(.internalServerError)
8585
}
86-
return .success(requestId: requestId, payload: payloadAsString)
86+
return .success((requestId: requestId, payload: payloadAsString))
8787
}
8888

8989
func processResponse(requestId _: String, response: String) -> ProcessResponseResult {
9090
guard let data = response.data(using: .utf8) else {
9191
XCTFail("decoding error")
92-
return .failure(.InternalServerError)
92+
return .failure(.internalServerError)
9393
}
9494
guard let response = try? JSONDecoder().decode(Res.self, from: data) else {
9595
XCTFail("decoding error")
96-
return .failure(.InternalServerError)
96+
return .failure(.internalServerError)
9797
}
9898
XCTAssertEqual(requestId, response.requestId, "expecting requestId to match")
9999
return .success()
100100
}
101101

102102
func processError(requestId _: String, error _: ErrorResponse) -> ProcessErrorResult {
103103
XCTFail("should not report error")
104-
return .failure(.InternalServerError)
104+
return .failure(.internalServerError)
105105
}
106106
}
107107

108108
private class BadBehavior: LambdaServerBehavior {
109109
func getWork() -> GetWorkResult {
110-
return .failure(.InternalServerError)
110+
return .failure(.internalServerError)
111111
}
112112

113113
func processResponse(requestId _: String, response _: String) -> ProcessResponseResult {
114-
return .failure(.InternalServerError)
114+
return .failure(.internalServerError)
115115
}
116116

117117
func processError(requestId _: String, error _: ErrorResponse) -> ProcessErrorResult {
118-
return .failure(.InternalServerError)
118+
return .failure(.internalServerError)
119119
}
120120
}
121121

Tests/SwiftAwsLambdaTests/Lambda+StringTest.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ private class GoodBehavior: LambdaServerBehavior {
7272
let requestId = NSUUID().uuidString
7373
let payload = "hello"
7474
func getWork() -> GetWorkResult {
75-
return .success(requestId: requestId, payload: payload)
75+
return .success((requestId: requestId, payload: payload))
7676
}
7777

7878
func processResponse(requestId: String, response: String) -> ProcessResponseResult {
@@ -83,21 +83,21 @@ private class GoodBehavior: LambdaServerBehavior {
8383

8484
func processError(requestId _: String, error _: ErrorResponse) -> ProcessErrorResult {
8585
XCTFail("should not report error")
86-
return .failure(.InternalServerError)
86+
return .failure(.internalServerError)
8787
}
8888
}
8989

9090
private class BadBehavior: LambdaServerBehavior {
9191
func getWork() -> GetWorkResult {
92-
return .failure(.InternalServerError)
92+
return .failure(.internalServerError)
9393
}
9494

9595
func processResponse(requestId _: String, response _: String) -> ProcessResponseResult {
96-
return .failure(.InternalServerError)
96+
return .failure(.internalServerError)
9797
}
9898

9999
func processError(requestId _: String, error _: ErrorResponse) -> ProcessErrorResult {
100-
return .failure(.InternalServerError)
100+
return .failure(.internalServerError)
101101
}
102102
}
103103

0 commit comments

Comments
 (0)