Skip to content

Commit 39da6d9

Browse files
committed
adoption of sendable
motivation: adopt to sendable requirments in swift 5.6 changes: * define sendable shims for protocols and structs that may be used in async context * adjust tests * add a test to make sure no warning are emittted
1 parent f2a0ef5 commit 39da6d9

File tree

8 files changed

+103
-20
lines changed

8 files changed

+103
-20
lines changed

Sources/AWSLambdaRuntimeCore/LambdaContext.swift

+19-13
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,15 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414

15+
#if compiler(>=5.6)
16+
@preconcurrency import Dispatch
17+
@preconcurrency import Logging
18+
@preconcurrency import NIOCore
19+
#else
1520
import Dispatch
1621
import Logging
1722
import NIOCore
23+
#endif
1824

1925
// MARK: - InitializationContext
2026

@@ -23,7 +29,7 @@ extension Lambda {
2329
/// The Lambda runtime generates and passes the `InitializationContext` to the Handlers
2430
/// ``ByteBufferLambdaHandler/makeHandler(context:)`` or ``LambdaHandler/init(context:)``
2531
/// as an argument.
26-
public struct InitializationContext {
32+
public struct InitializationContext: _AWSLambdaSendable {
2733
/// `Logger` to log with
2834
///
2935
/// - note: The `LogLevel` can be configured using the `LOG_LEVEL` environment variable.
@@ -62,17 +68,17 @@ extension Lambda {
6268

6369
/// Lambda runtime context.
6470
/// The Lambda runtime generates and passes the `Context` to the Lambda handler as an argument.
65-
public struct LambdaContext: CustomDebugStringConvertible {
66-
final class _Storage {
67-
var requestID: String
68-
var traceID: String
69-
var invokedFunctionARN: String
70-
var deadline: DispatchWallTime
71-
var cognitoIdentity: String?
72-
var clientContext: String?
73-
var logger: Logger
74-
var eventLoop: EventLoop
75-
var allocator: ByteBufferAllocator
71+
public struct LambdaContext: CustomDebugStringConvertible, _AWSLambdaSendable {
72+
final class _Storage: _AWSLambdaSendable {
73+
let requestID: String
74+
let traceID: String
75+
let invokedFunctionARN: String
76+
let deadline: DispatchWallTime
77+
let cognitoIdentity: String?
78+
let clientContext: String?
79+
let logger: Logger
80+
let eventLoop: EventLoop
81+
let allocator: ByteBufferAllocator
7682

7783
init(
7884
requestID: String,
@@ -211,7 +217,7 @@ public struct LambdaContext: CustomDebugStringConvertible {
211217
extension Lambda {
212218
/// Lambda runtime shutdown context.
213219
/// The Lambda runtime generates and passes the `ShutdownContext` to the Lambda handler as an argument.
214-
public final class ShutdownContext {
220+
public final class ShutdownContext: _AWSLambdaSendable {
215221
/// `Logger` to log with
216222
///
217223
/// - note: The `LogLevel` can be configured using the `LOG_LEVEL` environment variable.

Sources/AWSLambdaRuntimeCore/LambdaHandler.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import NIOCore
2626
/// level protocols ``EventLoopLambdaHandler`` and
2727
/// ``ByteBufferLambdaHandler``.
2828
@available(macOS 12, iOS 15, tvOS 15, watchOS 8, *)
29-
public protocol LambdaHandler: EventLoopLambdaHandler {
29+
public protocol LambdaHandler: EventLoopLambdaHandler where Event: _AWSLambdaSendable {
3030
/// The Lambda initialization method
3131
/// Use this method to initialize resources that will be used in every request.
3232
///
@@ -157,7 +157,7 @@ extension EventLoopLambdaHandler where Output == Void {
157157
/// - note: This is a low level protocol designed to power the higher level ``EventLoopLambdaHandler`` and
158158
/// ``LambdaHandler`` based APIs.
159159
/// Most users are not expected to use this protocol.
160-
public protocol ByteBufferLambdaHandler {
160+
public protocol ByteBufferLambdaHandler: _ByteBufferLambdaHandlerSendable {
161161
/// Create your Lambda handler for the runtime.
162162
///
163163
/// Use this to initialize all your resources that you want to cache between invocations. This could be database

Sources/AWSLambdaRuntimeCore/LambdaRunner.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ extension Lambda {
3737
func initialize<Handler: ByteBufferLambdaHandler>(logger: Logger, handlerType: Handler.Type) -> EventLoopFuture<Handler> {
3838
logger.debug("initializing lambda")
3939
// 1. create the handler from the factory
40-
// 2. report initialization error if one occured
40+
// 2. report initialization error if one occurred
4141
let context = InitializationContext(logger: logger,
4242
eventLoop: self.eventLoop,
4343
allocator: self.allocator)

Sources/AWSLambdaRuntimeCore/LambdaRuntimeClient.swift

+5
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,13 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import Logging
16+
#if compiler(>=5.6)
17+
@preconcurrency import NIOCore
18+
@preconcurrency import NIOHTTP1
19+
#else
1620
import NIOCore
1721
import NIOHTTP1
22+
#endif
1823

1924
/// An HTTP based client for AWS Runtime Engine. This encapsulates the RESTful methods exposed by the Runtime Engine:
2025
/// * /runtime/invocation/next
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the SwiftAWSLambdaRuntime open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the SwiftAWSLambdaRuntime project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
// Sendable bridging types
16+
17+
#if compiler(>=5.6)
18+
@preconcurrency public protocol _ByteBufferLambdaHandlerSendable: Sendable {}
19+
#else
20+
public protocol _ByteBufferLambdaHandlerSendable {}
21+
#endif
22+
23+
#if compiler(>=5.6)
24+
public typealias _AWSLambdaSendable = Sendable
25+
#else
26+
public typealias _AWSLambdaSendable = Any
27+
#endif

Sources/AWSLambdaTesting/Lambda+Testing.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ extension Lambda {
5151
public init(requestID: String = "\(DispatchTime.now().uptimeNanoseconds)",
5252
traceID: String = "Root=\(DispatchTime.now().uptimeNanoseconds);Parent=\(DispatchTime.now().uptimeNanoseconds);Sampled=1",
5353
invokedFunctionARN: String = "arn:aws:lambda:us-west-1:\(DispatchTime.now().uptimeNanoseconds):function:custom-runtime",
54-
timeout: DispatchTimeInterval = .seconds(5))
55-
{
54+
timeout: DispatchTimeInterval = .seconds(5)) {
5655
self.requestID = requestID
5756
self.traceID = traceID
5857
self.invokedFunctionARN = invokedFunctionARN

Tests/AWSLambdaRuntimeCoreTests/LambdaTest.swift

+47-1
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,14 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
@testable import AWSLambdaRuntimeCore
16+
#if compiler(>=5.6)
17+
@preconcurrency import Logging
18+
@preconcurrency import NIOPosix
19+
#else
1620
import Logging
17-
import NIOCore
1821
import NIOPosix
22+
#endif
23+
import NIOCore
1924
import XCTest
2025

2126
class LambdaTest: XCTestCase {
@@ -250,6 +255,47 @@ class LambdaTest: XCTestCase {
250255
XCTAssertLessThanOrEqual(context.getRemainingTime(), .seconds(1))
251256
XCTAssertGreaterThan(context.getRemainingTime(), .milliseconds(800))
252257
}
258+
259+
#if compiler(>=5.6)
260+
func testSendable() async throws {
261+
struct Handler: EventLoopLambdaHandler {
262+
typealias Event = String
263+
typealias Output = String
264+
265+
static func makeHandler(context: Lambda.InitializationContext) -> EventLoopFuture<Handler> {
266+
context.eventLoop.makeSucceededFuture(Handler())
267+
}
268+
269+
func handle(_ event: String, context: LambdaContext) -> EventLoopFuture<String> {
270+
context.eventLoop.makeSucceededFuture("hello")
271+
}
272+
}
273+
274+
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
275+
defer { XCTAssertNoThrow(try eventLoopGroup.syncShutdownGracefully()) }
276+
277+
let server = try MockLambdaServer(behavior: Behavior()).start().wait()
278+
defer { XCTAssertNoThrow(try server.stop().wait()) }
279+
280+
let logger = Logger(label: "TestLogger")
281+
let configuration = Lambda.Configuration(runtimeEngine: .init(requestTimeout: .milliseconds(100)))
282+
283+
let handler1 = Handler()
284+
let task = Task.detached {
285+
print(configuration.description)
286+
logger.info("hello")
287+
let runner = Lambda.Runner(eventLoop: eventLoopGroup.next(), configuration: configuration)
288+
289+
try runner.run(logger: logger, handler: handler1).wait()
290+
291+
try runner.initialize(logger: logger, handlerType: Handler.self).flatMap { handler2 in
292+
runner.run(logger: logger, handler: handler2)
293+
}.wait()
294+
}
295+
296+
try await task.value
297+
}
298+
#endif
253299
}
254300

255301
private struct Behavior: LambdaServerBehavior {

docker/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ RUN echo 'export PATH="$HOME/.tools:$PATH"' >> $HOME/.profile
1515

1616
# swiftformat (until part of the toolchain)
1717

18-
ARG swiftformat_version=0.47.3
18+
ARG swiftformat_version=0.49.6
1919
RUN git clone --branch $swiftformat_version --depth 1 https://github.com/nicklockwood/SwiftFormat $HOME/.tools/swift-format
2020
RUN cd $HOME/.tools/swift-format && swift build -c release
2121
RUN ln -s $HOME/.tools/swift-format/.build/release/swiftformat $HOME/.tools/swiftformat

0 commit comments

Comments
 (0)