Skip to content
This repository was archived by the owner on Mar 19, 2024. It is now read-only.

Commit c2289e1

Browse files
- Refactoring NIO Lambda Handlers Implementation
- Add documentation
1 parent 597686e commit c2289e1

File tree

3 files changed

+240
-13
lines changed

3 files changed

+240
-13
lines changed

Sources/LambdaSwiftSprinterNioPlugin/NIOLambdaHandler.swift

Lines changed: 229 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,229 @@ import NIOHTTP1
1818
import NIOFoundationCompat
1919
import LambdaSwiftSprinter
2020

21-
public typealias AsyncDictionaryNIOLambda = ([String: Any], Context, @escaping (DictionaryResult) -> Void) -> Void
21+
/**
22+
`SyncCodableNIOLambda<Event: Decodable, Response: Encodable>` lambda handler typealias.
23+
24+
- Usage example:
25+
26+
```
27+
import AsyncHTTPClient
28+
import Foundation
29+
#if canImport(FoundationNetworking)
30+
import FoundationNetworking
31+
#endif
32+
import LambdaSwiftSprinter
33+
import LambdaSwiftSprinterNioPlugin
34+
import Logging
35+
import NIO
36+
import NIOFoundationCompat
37+
38+
struct Event: Codable {
39+
let url: String
40+
}
41+
42+
struct Response: Codable {
43+
let url: String
44+
let content: String
45+
}
46+
47+
let syncCodableNIOLambda: SyncCodableNIOLambda<Event, Response> = { (event, context) throws -> EventLoopFuture<Response> in
48+
49+
let request = try HTTPClient.Request(url: event.url)
50+
let future = httpClient.execute(request: request, deadline: nil)
51+
.flatMapThrowing { (response) throws -> String in
52+
guard let body = response.body,
53+
let value = body.getString(at: 0, length: body.readableBytes) else {
54+
throw SprinterError.invalidJSON
55+
}
56+
return value
57+
}.map { content -> Response in
58+
return Response(url: event.url, content: content)
59+
}
60+
return future
61+
}
62+
do {
63+
let sprinter = try SprinterNIO()
64+
sprinter.register(handler: "getHttps", lambda: syncCodableNIOLambda)
65+
66+
try sprinter.run()
67+
} catch {
68+
//log the error
69+
}
70+
```
71+
*/
72+
public typealias SyncCodableNIOLambda<Event: Decodable, Response: Encodable> = (Event, Context) throws -> EventLoopFuture<Response>
73+
74+
/**
75+
`SyncDictionaryNIOLambda` lambda handler typealias.
76+
77+
- Usage example:
78+
79+
```
80+
import AsyncHTTPClient
81+
import Foundation
82+
#if canImport(FoundationNetworking)
83+
import FoundationNetworking
84+
#endif
85+
import LambdaSwiftSprinter
86+
import LambdaSwiftSprinterNioPlugin
87+
import Logging
88+
import NIO
89+
import NIOFoundationCompat
90+
91+
enum MyError: Error {
92+
case invalidParameters
93+
}
94+
95+
let syncDictionaryNIOLambda: SyncDictionaryNIOLambda = { (event, context) throws -> EventLoopFuture<[String: Any]> in
96+
97+
guard let url = event["url"] as? String else {
98+
throw MyError.invalidParameters
99+
}
100+
101+
let request = try HTTPClient.Request(url: url)
102+
let future = httpClient.execute(request: request, deadline: nil)
103+
.flatMapThrowing { (response) throws -> String in
104+
guard let body = response.body,
105+
let value = body.getString(at: 0, length: body.readableBytes) else {
106+
throw SprinterError.invalidJSON
107+
}
108+
return value
109+
}.map { content -> [String: Any] in
110+
return ["url": url,
111+
"content": content]
112+
}
113+
return future
114+
}
115+
do {
116+
let sprinter = try SprinterNIO()
117+
sprinter.register(handler: "getHttps", lambda: syncDictionaryNIOLambda)
118+
119+
try sprinter.run()
120+
} catch {
121+
//log the error
122+
}
123+
```
124+
*/
125+
public typealias SyncDictionaryNIOLambda = ([String: Any], Context) throws -> EventLoopFuture<[String: Any]>
126+
127+
128+
/**
129+
`AsyncCodableNIOLambda<Event: Decodable, Response: Encodable>` lambda handler typealias.
130+
131+
- Parameter
132+
133+
- Usage example:
134+
135+
```
136+
import AsyncHTTPClient
137+
import Foundation
138+
#if canImport(FoundationNetworking)
139+
import FoundationNetworking
140+
#endif
141+
import LambdaSwiftSprinter
142+
import LambdaSwiftSprinterNioPlugin
143+
import Logging
144+
import NIO
145+
import NIOFoundationCompat
146+
147+
struct Event: Codable {
148+
let url: String
149+
}
150+
151+
struct Response: Codable {
152+
let url: String
153+
let content: String
154+
}
155+
156+
let asyncCodableNIOLambda: AsyncCodableNIOLambda<Event, Response> = { (event, context, completion) -> Void in
157+
do {
158+
let request = try HTTPClient.Request(url: event.url)
159+
let reponse: Response = try httpClient.execute(request: request, deadline: nil)
160+
.flatMapThrowing { (response) throws -> String in
161+
guard let body = response.body,
162+
let value = body.getString(at: 0, length: body.readableBytes) else {
163+
throw SprinterError.invalidJSON
164+
}
165+
return value
166+
}.map { content -> Response in
167+
return Response(url: event.url, content: content)
168+
}
169+
.wait()
170+
completion(.success(reponse))
171+
} catch {
172+
completion(.failure(error))
173+
}
174+
}
175+
do {
176+
let sprinter = try SprinterNIO()
177+
sprinter.register(handler: "getHttps", lambda: asyncCodableNIOLambda)
178+
179+
try sprinter.run()
180+
} catch {
181+
//log the error
182+
}
183+
```
184+
*/
22185
public typealias AsyncCodableNIOLambda<Event: Decodable, Response: Encodable> = (Event, Context, @escaping (Result<Response, Error>) -> Void) -> Void
23186

24-
public typealias SyncDictionaryNIOLambda = ([String: Any], Context) throws -> [String: Any]
25-
public typealias SyncCodableNIOLambda<Event: Decodable, Response: Encodable> = (Event, Context) -> EventLoopFuture<Response>
187+
188+
/**
189+
`AsyncDictionaryNIOLambda` lambda handler typealias.
190+
191+
- Usage example:
192+
193+
```
194+
import AsyncHTTPClient
195+
import Foundation
196+
#if canImport(FoundationNetworking)
197+
import FoundationNetworking
198+
#endif
199+
import LambdaSwiftSprinter
200+
import LambdaSwiftSprinterNioPlugin
201+
import Logging
202+
import NIO
203+
import NIOFoundationCompat
204+
205+
enum MyError: Error {
206+
case invalidParameters
207+
}
208+
209+
let asynchDictionayNIOLambda: AsyncDictionaryNIOLambda = { (event, context, completion) -> Void in
210+
guard let url = event["url"] as? String else {
211+
completion(.failure(MyError.invalidParameters))
212+
return
213+
}
214+
do {
215+
let request = try HTTPClient.Request(url: url)
216+
let dictionary: [String: Any] = try httpClient.execute(request: request, deadline: nil)
217+
.flatMapThrowing { (response) throws -> String in
218+
guard let body = response.body,
219+
let value = body.getString(at: 0, length: body.readableBytes) else {
220+
throw SprinterError.invalidJSON
221+
}
222+
return value
223+
}.map { content -> [String: Any] in
224+
return ["url": url,
225+
"content": content]
226+
}
227+
.wait()
228+
completion(.success(dictionary))
229+
} catch {
230+
completion(.failure(error))
231+
}
232+
}
233+
do {
234+
let sprinter = try SprinterNIO()
235+
sprinter.register(handler: "getHttps", lambda: asynchDictionayNIOLambda)
236+
237+
try sprinter.run()
238+
} catch {
239+
//log the error
240+
}
241+
```
242+
*/
243+
public typealias AsyncDictionaryNIOLambda = ([String: Any], Context, @escaping (DictionaryResult) -> Void) -> Void
26244

27245
public protocol SyncNIOLambdaHandler: LambdaHandler {
28246

@@ -70,7 +288,7 @@ public extension AsyncNIOLambdaHandler {
70288

71289
struct CodableSyncNIOLambdaHandler<Event: Decodable, Response: Encodable>: SyncNIOLambdaHandler {
72290

73-
let handlerFunction: (Event, Context) -> EventLoopFuture<Response>
291+
let handlerFunction: (Event, Context) throws -> EventLoopFuture<Response>
74292

75293
func handler(event: Data, context: Context) -> EventLoopFuture<Data> {
76294

@@ -115,16 +333,19 @@ struct CodableAsyncNIOLambdaHandler<Event: Decodable, Response: Encodable>: Asyn
115333

116334
struct DictionarySyncNIOLambdaHandler: SyncNIOLambdaHandler {
117335

118-
let completionHandler: ([String: Any], Context) throws -> [String: Any]
336+
let completionHandler: ([String: Any], Context) throws -> EventLoopFuture<[String: Any]>
119337
func handler(event: Data, context: Context) -> EventLoopFuture<Data> {
120-
338+
121339
let eventLoop = httpClient.eventLoopGroup.next()
122340
let promise = eventLoop.makePromise(of: Data.self)
123341
do {
124342
let data = try event.jsonObject()
125343
let output = try completionHandler(data, context)
126-
let responseObj = try Data(jsonObject: output)
127-
promise.succeed(responseObj)
344+
.flatMapThrowing{ (dictionary) -> Data in
345+
return try Data(jsonObject: dictionary)
346+
}
347+
.wait()
348+
promise.succeed(output)
128349
} catch {
129350
promise.fail(error)
130351
}

Tests/LambdaSwiftSprinterNioPluginTests/NIOLambdaHandlerTests.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,11 @@ final class NIOLambdaHandlerTests: XCTestCase {
8989

9090
func testDictionarySyncNIOLambdaHandler() {
9191
// When valid Data and valid completionHandler
92-
let lambda = DictionarySyncNIOLambdaHandler { (dictionary, _) -> [String: Any] in
93-
dictionary
92+
let lambda = DictionarySyncNIOLambdaHandler { (dictionary, _) -> EventLoopFuture<[String: Any]> in
93+
let eventloop = httpClient.eventLoopGroup.next()
94+
let promise = eventloop.makePromise(of: [String: Any].self)
95+
promise.succeed(dictionary)
96+
return promise.futureResult
9497
}
9598
let result = try? lambda.handler(event: validData,
9699
context: validContext).wait()
@@ -101,7 +104,7 @@ final class NIOLambdaHandlerTests: XCTestCase {
101104
context: validContext).wait())
102105

103106
// When valid Data and invalid completionHandler
104-
let lambda2 = DictionarySyncNIOLambdaHandler { (_, _) -> [String: Any] in
107+
let lambda2 = DictionarySyncNIOLambdaHandler { (_, _) -> EventLoopFuture<[String: Any]> in
105108
throw ErrorMock.someError
106109
}
107110

Tests/LambdaSwiftSprinterNioPluginTests/SprinterNIOTests.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ final class SprinterNIOTests: XCTestCase {
5757
"_HANDLER": "Lambda.handler"]
5858
let sprinter = try? Sprinter<LambdaApiNIO>(environment: environment)
5959

60-
let completion: SyncDictionaryNIOLambda = { (_, _) -> [String: Any] in
61-
["": ""]
60+
let completion: SyncDictionaryNIOLambda = { (_, _) -> EventLoopFuture<[String: Any]> in
61+
let eventloop = httpClient.eventLoopGroup.next()
62+
let promise = eventloop.makePromise(of: [String: Any].self)
63+
promise.succeed(["":""])
64+
return promise.futureResult
6265
}
6366
sprinter?.register(handler: "handler", lambda: completion)
6467

0 commit comments

Comments
 (0)