Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@

import PackageDescription

let defaultSwiftSettings: [SwiftSetting] =
[
.enableExperimentalFeature(
"AvailabilityMacro=LambdaSwift 2.0:macOS 15.0"
)
]

let package = Package(
name: "swift-aws-lambda-runtime",
platforms: [.macOS(.v15)],
products: [
.library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]),
// plugin to package the lambda, creating an archive that can be uploaded to AWS
Expand Down Expand Up @@ -43,7 +49,8 @@ let package = Package(
package: "swift-service-lifecycle",
condition: .when(traits: ["ServiceLifecycleSupport"])
),
]
],
swiftSettings: defaultSwiftSettings
),
.plugin(
name: "AWSLambdaPackager",
Expand All @@ -67,8 +74,10 @@ let package = Package(
.byName(name: "AWSLambdaRuntime"),
.product(name: "NIOTestUtils", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
]
],
swiftSettings: defaultSwiftSettings
),

// for perf testing
.executableTarget(
name: "MockServer",
Expand All @@ -77,7 +86,8 @@ let package = Package(
.product(name: "NIOHTTP1", package: "swift-nio"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOPosix", package: "swift-nio"),
]
],
swiftSettings: defaultSwiftSettings
),
]
)
25 changes: 13 additions & 12 deletions [email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@

import PackageDescription

let defaultSwiftSettings: [SwiftSetting] = [
.define("FoundationJSONSupport"),
.define("ServiceLifecycleSupport"),
.define("LocalServerSupport"),
.enableExperimentalFeature(
"AvailabilityMacro=LambdaSwift 2.0:macOS 15.0"
),
]

let package = Package(
name: "swift-aws-lambda-runtime",
platforms: [.macOS(.v15)],
products: [
.library(name: "AWSLambdaRuntime", targets: ["AWSLambdaRuntime"]),
// plugin to package the lambda, creating an archive that can be uploaded to AWS
Expand All @@ -28,11 +36,7 @@ let package = Package(
.product(name: "NIOPosix", package: "swift-nio"),
.product(name: "ServiceLifecycle", package: "swift-service-lifecycle"),
],
swiftSettings: [
.define("FoundationJSONSupport"),
.define("ServiceLifecycleSupport"),
.define("LocalServerSupport"),
]
swiftSettings: defaultSwiftSettings
),
.plugin(
name: "AWSLambdaPackager",
Expand All @@ -57,11 +61,7 @@ let package = Package(
.product(name: "NIOTestUtils", package: "swift-nio"),
.product(name: "NIOFoundationCompat", package: "swift-nio"),
],
swiftSettings: [
.define("FoundationJSONSupport"),
.define("ServiceLifecycleSupport"),
.define("LocalServerSupport"),
]
swiftSettings: defaultSwiftSettings
),
// for perf testing
.executableTarget(
Expand All @@ -71,7 +71,8 @@ let package = Package(
.product(name: "NIOHTTP1", package: "swift-nio"),
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOPosix", package: "swift-nio"),
]
],
swiftSettings: defaultSwiftSettings
),
]
)
3 changes: 3 additions & 0 deletions Sources/AWSLambdaRuntime/ControlPlaneRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,23 @@
import NIOCore
import NIOHTTP1

@available(LambdaSwift 2.0, *)
enum ControlPlaneRequest: Hashable {
case next
case invocationResponse(String, ByteBuffer?)
case invocationError(String, ErrorResponse)
case initializationError(ErrorResponse)
}

@available(LambdaSwift 2.0, *)
enum ControlPlaneResponse: Hashable {
case next(InvocationMetadata, ByteBuffer)
case accepted
case error(ErrorResponse)
}

@usableFromInline
@available(LambdaSwift 2.0, *)
package struct InvocationMetadata: Hashable, Sendable {
@usableFromInline
package let requestID: String
Expand Down
1 change: 1 addition & 0 deletions Sources/AWSLambdaRuntime/ControlPlaneRequestEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

import NIOCore

@available(LambdaSwift 2.0, *)
struct ControlPlaneRequestEncoder: _EmittingChannelHandler {
typealias OutboundOut = ByteBuffer

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import FoundationEssentials
import struct Foundation.Date
#endif

@available(LambdaSwift 2.0, *)
extension LambdaContext {
/// Returns the deadline as a Date for the Lambda function execution.
/// I'm not sure how usefull it is to have this as a Date, with only seconds precision,
Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/FoundationSupport/Lambda+JSON.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public struct LambdaJSONOutputEncoder<Output: Encodable>: LambdaOutputEncoder {
}
}

@available(LambdaSwift 2.0, *)
extension LambdaCodableAdapter {
/// Initializes an instance given an encoder, decoder, and a handler with a non-`Void` output.
/// - Parameters:
Expand All @@ -84,6 +85,7 @@ extension LambdaCodableAdapter {
}
}

@available(LambdaSwift 2.0, *)
extension LambdaRuntime {
/// Initialize an instance with a `LambdaHandler` defined in the form of a closure **with a non-`Void` return type**.
/// - Parameters:
Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/Lambda+Codable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public struct VoidEncoder: LambdaOutputEncoder {
}

/// Adapts a ``LambdaHandler`` conforming handler to conform to ``LambdaWithBackgroundProcessingHandler``.
@available(LambdaSwift 2.0, *)
public struct LambdaHandlerAdapter<
Event: Decodable,
Output,
Expand Down Expand Up @@ -80,6 +81,7 @@ public struct LambdaHandlerAdapter<
}

/// Adapts a ``LambdaWithBackgroundProcessingHandler`` conforming handler to conform to ``StreamingLambdaHandler``.
@available(LambdaSwift 2.0, *)
public struct LambdaCodableAdapter<
Handler: LambdaWithBackgroundProcessingHandler,
Event: Decodable,
Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/Lambda+LocalServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import Synchronization
// )
// }
// }
@available(LambdaSwift 2.0, *)
extension Lambda {
/// Execute code in the context of a mock Lambda server.
///
Expand Down Expand Up @@ -84,6 +85,7 @@ extension Lambda {
/// 1. POST /invoke - the client posts the event to the lambda function
///
/// This server passes the data received from /invoke POST request to the lambda function (GET /next) and then forwards the response back to the client.
@available(LambdaSwift 2.0, *)
internal struct LambdaHTTPServer {
private let invocationEndpoint: String

Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/Lambda.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import ucrt
#error("Unsupported platform")
#endif

@available(LambdaSwift 2.0, *)
public enum Lambda {
@inlinable
package static func runLoop<RuntimeClient: LambdaRuntimeClientProtocol, Handler>(
Expand Down Expand Up @@ -98,6 +99,7 @@ public enum Lambda {

// MARK: - Public API

@available(LambdaSwift 2.0, *)
extension Lambda {
/// Utility to access/read environment variables
public static func env(_ name: String) -> String? {
Expand Down
1 change: 1 addition & 0 deletions Sources/AWSLambdaRuntime/LambdaClock.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import ucrt
/// The Lambda execution environment uses UTC as a timezone,
/// `LambdaClock` operates in UTC and does not account for time zones.
/// see: TZ in https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html
@available(LambdaSwift 2.0, *)
public struct LambdaClock: Clock {
public typealias Duration = Swift.Duration

Expand Down
1 change: 1 addition & 0 deletions Sources/AWSLambdaRuntime/LambdaContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public struct ClientContext: Codable, Sendable {

/// Lambda runtime context.
/// The Lambda runtime generates and passes the `LambdaContext` to the Lambda handler as an argument.
@available(LambdaSwift 2.0, *)
public struct LambdaContext: CustomDebugStringConvertible, Sendable {
final class _Storage: Sendable {
let requestID: String
Expand Down
6 changes: 6 additions & 0 deletions Sources/AWSLambdaRuntime/LambdaHandlers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import NIOCore
/// Background work can also be executed after returning the response. After closing the response stream by calling
/// ``LambdaResponseStreamWriter/finish()`` or ``LambdaResponseStreamWriter/writeAndFinish(_:)``,
/// the ``handle(_:responseWriter:context:)`` function is free to execute any background work.
@available(LambdaSwift 2.0, *)
public protocol StreamingLambdaHandler: _Lambda_SendableMetatype {
/// The handler function -- implement the business logic of the Lambda function here.
/// - Parameters:
Expand Down Expand Up @@ -66,6 +67,7 @@ public protocol LambdaResponseStreamWriter {
///
/// - note: This handler protocol does not support response streaming because the output has to be encoded prior to it being sent, e.g. it is not possible to encode a partial/incomplete JSON string.
/// This protocol also does not support the execution of background work after the response has been returned -- the ``LambdaWithBackgroundProcessingHandler`` protocol caters for such use-cases.
@available(LambdaSwift 2.0, *)
public protocol LambdaHandler {
/// Generic input type.
/// The body of the request sent to Lambda will be decoded into this type for the handler to consume.
Expand All @@ -88,6 +90,7 @@ public protocol LambdaHandler {
/// ``LambdaResponseWriter``that is passed in as an argument, meaning that the
/// ``LambdaWithBackgroundProcessingHandler/handle(_:outputWriter:context:)`` function is then
/// free to implement any background work after the result has been sent to the AWS Lambda control plane.
@available(LambdaSwift 2.0, *)
public protocol LambdaWithBackgroundProcessingHandler {
/// Generic input type.
/// The body of the request sent to Lambda will be decoded into this type for the handler to consume.
Expand Down Expand Up @@ -123,6 +126,7 @@ public protocol LambdaResponseWriter<Output> {

/// A ``StreamingLambdaHandler`` conforming handler object that can be constructed with a closure.
/// Allows for a handler to be defined in a clean manner, leveraging Swift's trailing closure syntax.
@available(LambdaSwift 2.0, *)
public struct StreamingClosureHandler: StreamingLambdaHandler {
let body: @Sendable (ByteBuffer, LambdaResponseStreamWriter, LambdaContext) async throws -> Void

Expand Down Expand Up @@ -151,6 +155,7 @@ public struct StreamingClosureHandler: StreamingLambdaHandler {

/// A ``LambdaHandler`` conforming handler object that can be constructed with a closure.
/// Allows for a handler to be defined in a clean manner, leveraging Swift's trailing closure syntax.
@available(LambdaSwift 2.0, *)
public struct ClosureHandler<Event: Decodable, Output>: LambdaHandler {
let body: (Event, LambdaContext) async throws -> Output

Expand All @@ -175,6 +180,7 @@ public struct ClosureHandler<Event: Decodable, Output>: LambdaHandler {
}
}

@available(LambdaSwift 2.0, *)
extension LambdaRuntime {
/// Initialize an instance with a ``StreamingLambdaHandler`` in the form of a closure.
/// - Parameter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ extension LambdaResponseStreamWriter {
}
}

@available(LambdaSwift 2.0, *)
extension LambdaResponseStreamWriter {
/// Writes the HTTP status code and headers to the response stream.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#if ServiceLifecycleSupport
import ServiceLifecycle

@available(LambdaSwift 2.0, *)
extension LambdaRuntime: Service {
public func run() async throws {
try await cancelWhenGracefulShutdown {
Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/LambdaRuntime.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import Foundation

// This is our guardian to ensure only one LambdaRuntime is running at the time
// We use an Atomic here to ensure thread safety
@available(LambdaSwift 2.0, *)
private let _isRunning = Atomic<Bool>(false)

@available(LambdaSwift 2.0, *)
public final class LambdaRuntime<Handler>: Sendable where Handler: StreamingLambdaHandler {
@usableFromInline
/// we protect the handler behind a Mutex to ensure that we only ever have one copy of it
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal protocol LambdaChannelHandlerDelegate {
func connectionErrorHappened(_ error: any Error, channel: any Channel)
}

@available(LambdaSwift 2.0, *)
internal final class LambdaChannelHandler<Delegate: LambdaChannelHandlerDelegate> {
let nextInvocationPath = Consts.invocationURLPrefix + Consts.getNextInvocationURLSuffix

Expand Down Expand Up @@ -359,6 +360,7 @@ internal final class LambdaChannelHandler<Delegate: LambdaChannelHandlerDelegate
}
}

@available(LambdaSwift 2.0, *)
extension LambdaChannelHandler: ChannelInboundHandler {
typealias OutboundIn = Never
typealias InboundIn = NIOHTTPClientResponseFull
Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import NIOCore
import NIOHTTP1
import NIOPosix

@available(LambdaSwift 2.0, *)
@usableFromInline
final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
@usableFromInline
Expand Down Expand Up @@ -404,6 +405,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
}
}

@available(LambdaSwift 2.0, *)
extension LambdaRuntimeClient: LambdaChannelHandlerDelegate {
nonisolated func connectionErrorHappened(_ error: any Error, channel: any Channel) {}

Expand Down
2 changes: 2 additions & 0 deletions Sources/AWSLambdaRuntime/LambdaRuntimeClientProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ package protocol LambdaRuntimeClientResponseStreamWriter: LambdaResponseStreamWr
}

@usableFromInline
@available(LambdaSwift 2.0, *)
package protocol LambdaRuntimeClientProtocol {
associatedtype Writer: LambdaRuntimeClientResponseStreamWriter

func nextInvocation() async throws -> (Invocation, Writer)
}

@usableFromInline
@available(LambdaSwift 2.0, *)
package struct Invocation: Sendable {
@usableFromInline
package var metadata: InvocationMetadata
Expand Down
1 change: 1 addition & 0 deletions Sources/AWSLambdaRuntime/Utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ extension String {
}
}

@available(LambdaSwift 2.0, *)
extension AmazonHeaders {
/// Generates (X-Ray) trace ID.
/// # Trace ID Format
Expand Down
1 change: 1 addition & 0 deletions Sources/MockServer/MockHTTPServer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import FoundationEssentials
import Foundation
#endif

@available(LambdaSwift 2.0, *)
@main
struct HttpServer {
/// The server's host. (default: 127.0.0.1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import Logging
import Synchronization
import Testing

@available(LambdaSwift 2.0, *)
struct CollectEverythingLogHandler: LogHandler {
var metadata: Logger.Metadata = [:]
var logLevel: Logger.Level = .info
Expand Down
Loading