Skip to content

Commit 9bad867

Browse files
committed
Full scenario example for Lambda in Swift
This PR includes a complete implementation of the "basics" scenario example for the AWS SDK for Swift.
1 parent ba445cf commit 9bad867

File tree

10 files changed

+868
-111
lines changed

10 files changed

+868
-111
lines changed

swift/example_code/lambda/basics/Sources/ExampleError.swift

Lines changed: 0 additions & 21 deletions
This file was deleted.

swift/example_code/lambda/basics/Sources/entry.swift

Lines changed: 0 additions & 86 deletions
This file was deleted.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// swift-tools-version: 5.9
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// The swift-tools-version declares the minimum version of Swift required to
6+
// build this package.
7+
8+
import PackageDescription
9+
10+
let package = Package(
11+
name: "calculator",
12+
// Let Xcode know the minimum Apple platforms supported.
13+
platforms: [
14+
.macOS(.v13)
15+
],
16+
dependencies: [
17+
// Dependencies declare other packages that this package depends on.
18+
.package(
19+
url: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
20+
from: "1.0.0-alpha"),
21+
],
22+
targets: [
23+
// Targets are the basic building blocks of a package, defining a module or a test suite.
24+
// Targets can depend on other targets in this package and products
25+
// from dependencies.
26+
.executableTarget(
27+
name: "calculator",
28+
dependencies: [
29+
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
30+
],
31+
path: "Sources"
32+
)
33+
]
34+
)
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
// snippet-start:[lambda.swift.calculator.complete]
4+
// snippet-start:[lambda.swift.calculator.imports]
5+
import Foundation
6+
import AWSLambdaRuntime
7+
// snippet-end:[lambda.swift.calculator.imports]
8+
9+
// snippet-start:[lambda.swift.calculator.types]
10+
// snippet-start:[lambda.swift.calculator.struct.request]
11+
/// Represents the contents of the requests being received from the client.
12+
/// This structure must be `Decodable` to indicate that its initializer
13+
/// converts an external representation into this type.
14+
struct Request: Decodable, Sendable {
15+
/// The action to perform.
16+
let action: String
17+
/// The first number to act upon.
18+
let x: Int
19+
/// The second number to act upon.
20+
let y: Int
21+
}
22+
// snippet-end:[lambda.swift.calculator.struct.request]
23+
24+
// snippet-start:[lambda.swift.calculator.actions]
25+
/// A dictionary mapping operation names to closures that perform that
26+
/// operation and return the result.
27+
let actions = [
28+
"plus": { (x: Int, y: Int) -> Int in
29+
return x + y
30+
},
31+
"minus": { (x: Int, y: Int) -> Int in
32+
return x - y
33+
},
34+
"times": { (x: Int, y: Int) -> Int in
35+
return x * y
36+
},
37+
"divided-by": { (x: Int, y: Int) -> Int in
38+
return x / y
39+
}
40+
]
41+
// snippet-end:[lambda.swift.calculator.actions]
42+
43+
// snippet-start:[lambda.swift.calculator.struct.response]
44+
/// The contents of the response sent back to the client. This must be
45+
/// `Encodable`.
46+
struct Response: Encodable, Sendable {
47+
/// The resulting value after performing the action.
48+
let answer: Int?
49+
}
50+
// snippet-end:[lambda.swift.calculator.struct.response]
51+
52+
// snippet-end:[lambda.swift.calculator.types]
53+
54+
// snippet-start:[lambda.swift.calculator.handler]
55+
/// A Swift AWS Lambda Runtime `LambdaHandler` lets you both perform needed
56+
/// initialization and handle AWS Lambda requests. There are other handler
57+
/// protocols available for other use cases.
58+
@main
59+
struct CalculatorLambda: LambdaHandler {
60+
61+
// snippet-start:[lambda.swift.calculator.handler.init]
62+
/// Initialize the AWS Lambda runtime.
63+
///
64+
/// ^ The logger is a standard Swift logger. You can control the verbosity
65+
/// by setting the `LOG_LEVEL` environment variable.
66+
init(context: LambdaInitializationContext) async throws {
67+
// Display the `LOG_LEVEL` configuration for this process.
68+
context.logger.info(
69+
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )"
70+
)
71+
}
72+
// snippet-end:[lambda.swift.calculator.handler.init]
73+
74+
// snippet-start:[lambda.swift.calculator.handler.handle]
75+
/// The Lambda function's entry point. Called by the Lambda runtime.
76+
///
77+
/// - Parameters:
78+
/// - event: The `Request` describing the request made by the
79+
/// client.
80+
/// - context: A `LambdaContext` describing the context in
81+
/// which the lambda function is running.
82+
///
83+
/// - Returns: A `Response` object that will be encoded to JSON and sent
84+
/// to the client by the Lambda runtime.
85+
func handle(_ event: Request, context: LambdaContext) async throws -> Response {
86+
let action = event.action
87+
var answer: Int?
88+
var actionFunc: ((Int, Int) -> Int)?
89+
90+
// Get the closure to run to perform the calculation.
91+
92+
actionFunc = actions[action]
93+
94+
guard let actionFunc else {
95+
context.logger.error("Unrecognized operation '\(action)\'")
96+
return Response(answer: nil)
97+
}
98+
99+
// Perform the calculation and return the answer.
100+
101+
answer = actionFunc(event.x, event.y)
102+
103+
guard let answer else {
104+
context.logger.error("Error computing \(event.x) \(action) \(event.y)")
105+
}
106+
context.logger.info("\(event.x) \(action) \(event.y) = \(answer)")
107+
108+
return Response(answer: answer)
109+
}
110+
// snippet-end:[lambda.swift.calculator.handler.handle]
111+
}
112+
// snippet-end:[lambda.swift.calculator.handler]
113+
// snippet-end:[lambda.swift.calculator.complete]
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// swift-tools-version: 5.9
2+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// The swift-tools-version declares the minimum version of Swift required to
6+
// build this package.
7+
8+
import PackageDescription
9+
10+
let package = Package(
11+
name: "increment",
12+
// Let Xcode know the minimum Apple platforms supported.
13+
platforms: [
14+
.macOS(.v13)
15+
],
16+
dependencies: [
17+
// Dependencies declare other packages that this package depends on.
18+
.package(
19+
url: "https://github.com/swift-server/swift-aws-lambda-runtime.git",
20+
from: "1.0.0-alpha"),
21+
],
22+
targets: [
23+
// Targets are the basic building blocks of a package, defining a module or a test suite.
24+
// Targets can depend on other targets in this package and products
25+
// from dependencies.
26+
.executableTarget(
27+
name: "increment",
28+
dependencies: [
29+
.product(name: "AWSLambdaRuntime", package: "swift-aws-lambda-runtime"),
30+
],
31+
path: "Sources"
32+
)
33+
]
34+
)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
// snippet-start:[lambda.swift.increment.complete]
4+
// snippet-start:[lambda.swift.increment.imports]
5+
import Foundation
6+
import AWSLambdaRuntime
7+
// snippet-end:[lambda.swift.increment.imports]
8+
9+
// snippet-start:[lambda.swift.increment.types]
10+
// snippet-start:[lambda.swift.increment.struct.request]
11+
/// Represents the contents of the requests being received from the client.
12+
/// This structure must be `Decodable` to indicate that its initializer
13+
/// converts an external representation into this type.
14+
struct Request: Decodable, Sendable {
15+
/// The action to perform.
16+
let action: String
17+
/// The number to act upon.
18+
let number: Int
19+
}
20+
// snippet-end:[lambda.swift.increment.struct.request]
21+
22+
// snippet-start:[lambda.swift.increment.struct.response]
23+
/// The contents of the response sent back to the client. This must be
24+
/// `Encodable`.
25+
struct Response: Encodable, Sendable {
26+
/// The resulting value after performing the action.
27+
let answer: Int?
28+
}
29+
// snippet-end:[lambda.swift.increment.struct.response]
30+
31+
// snippet-end:[lambda.swift.increment.types]
32+
33+
// snippet-start:[lambda.swift.increment.handler]
34+
/// A Swift AWS Lambda Runtime `LambdaHandler` lets you both perform needed
35+
/// initialization and handle AWS Lambda requests. There are other handler
36+
/// protocols available for other use cases.
37+
@main
38+
struct IncrementLambda: LambdaHandler {
39+
40+
// snippet-start:[lambda.swift.increment.handler.init]
41+
/// Initialize the AWS Lambda runtime.
42+
///
43+
/// ^ The logger is a standard Swift logger. You can control the verbosity
44+
/// by setting the `LOG_LEVEL` environment variable.
45+
init(context: LambdaInitializationContext) async throws {
46+
// Display the `LOG_LEVEL` configuration for this process.
47+
context.logger.info(
48+
"Log Level env var : \(ProcessInfo.processInfo.environment["LOG_LEVEL"] ?? "info" )"
49+
)
50+
}
51+
// snippet-end:[lambda.swift.increment.handler.init]
52+
53+
// snippet-start:[lambda.swift.increment.handler.handle]
54+
/// The Lambda function's entry point. Called by the Lambda runtime.
55+
///
56+
/// - Parameters:
57+
/// - event: The `Request` describing the request made by the
58+
/// client.
59+
/// - context: A `LambdaContext` describing the context in
60+
/// which the lambda function is running.
61+
///
62+
/// - Returns: A `Response` object that will be encoded to JSON and sent
63+
/// to the client by the Lambda runtime.
64+
func handle(_ event: Request, context: LambdaContext) async throws -> Response {
65+
let action = event.action
66+
var answer: Int?
67+
68+
if action != "increment" {
69+
context.logger.error("Unrecognized operation: \"\(action)\". The only supported action is \"increment\".")
70+
} else {
71+
answer = event.number + 1
72+
context.logger.info("The calculated answer is \(answer!).")
73+
}
74+
75+
let response = Response(answer: answer)
76+
return response
77+
}
78+
// snippet-end:[lambda.swift.increment.handler.handle]
79+
}
80+
// snippet-end:[lambda.swift.increment.handler]
81+
// snippet-end:[lambda.swift.increment.complete]

swift/example_code/lambda/basics/Package.swift renamed to swift/example_code/lambda/basics/lambda-basics/Package.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ let package = Package(
1111
name: "lambda-basics",
1212
// Let Xcode know the minimum Apple platforms supported.
1313
platforms: [
14-
.macOS(.v13),
15-
.iOS(.v15)
14+
.macOS(.v13)
1615
],
1716
dependencies: [
1817
// Dependencies declare other packages that this package depends on.
@@ -33,8 +32,9 @@ let package = Package(
3332
dependencies: [
3433
.product(name: "AWSLambda", package: "aws-sdk-swift"),
3534
.product(name: "AWSIAM", package: "aws-sdk-swift"),
36-
.product(name: "ArgumentParser", package: "swift-argument-parser"),
35+
.product(name: "ArgumentParser", package: "swift-argument-parser")
3736
],
38-
path: "Sources"),
37+
path: "Sources"
38+
)
3939
]
4040
)

0 commit comments

Comments
 (0)