mirror of
https://github.com/swift-server/swift-aws-lambda-runtime.git
synced 2026-06-02 07:27:33 +00:00
Revert streaming codable handler change and propose it as an example instead of an handler API. **Motivation:** I made a mistake when submitting this PR https://github.com/swift-server/swift-aws-lambda-runtime/pull/532 It provides a Streaming+Codable handler that conveniently allows developers to write handlers with `Codable` events for streaming functions. This is a mistake for three reasons: - This is the only handler that assumes a Lamba Event structure as input. I added a minimal `FunctionUrlRequest` and `FunctionURLResponse` to avoid importing the AWS Lambda Events library. It is the first handler to be event-specific. I don't think the runtime should introduce event specific code. - The handler only works when Lambda functions are exposed through Function URLs. Streaming functions can also be invoke by API or CLI. - The handler hides `FunctionURLRequest` details (HTTP headers, query parameters, etc.) from developers Developers were unaware they were trading flexibility for convenience The lack of clear documentation about these limitations led to incorrect usage patterns and frustrated developers who needed full request control or were using other invocation methods. **Modifications:** - Removed the Streaming+Codable API from the library - Moved the Streaming+Codable code to an example - Added prominent warning section in the example README explaining the limitations - Clarified when to use Streaming+Codable vs ByteBuffer approaches - Added decision rule framework to help developers choose the right approach **Result:** The only API provided by the library to use Streaming Lambda functions is exposing the raw `ByteBuffer` as input, there is no more `Codable` handler for Streaming functions available in the API. I kept the `Streaming+Codable` code an example. After this change, developers have clear guidance on when to use each streaming approach: - Use streaming codable for Function URL + JSON payload + no request details needed - Use ByteBuffer StreamingLambdaHandler for full control, other invocation methods, or request metadata access This prevents misuse of the API and sets proper expectations about the handler's capabilities and limitations, leading to better developer experience and fewer integration issues.
72 lines
2.4 KiB
Swift
72 lines
2.4 KiB
Swift
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This source file is part of the SwiftAWSLambdaRuntime open source project
|
|
//
|
|
// Copyright (c) 2024 Apple Inc. and the SwiftAWSLambdaRuntime project authors
|
|
// Licensed under Apache License v2.0
|
|
//
|
|
// See LICENSE.txt for license information
|
|
// See CONTRIBUTORS.txt for the list of SwiftAWSLambdaRuntime project authors
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
import AWSLambdaRuntime
|
|
import NIOCore
|
|
|
|
#if canImport(FoundationEssentials)
|
|
import FoundationEssentials
|
|
#else
|
|
import Foundation
|
|
#endif
|
|
|
|
// Define your input event structure
|
|
struct StreamingRequest: Decodable {
|
|
let count: Int
|
|
let message: String
|
|
let delayMs: Int?
|
|
|
|
// Provide default values for optional fields
|
|
var delay: Int {
|
|
delayMs ?? 500
|
|
}
|
|
}
|
|
|
|
// Use the new streaming handler with JSON decoding
|
|
let runtime = LambdaRuntime { (event: StreamingRequest, responseWriter, context: LambdaContext) in
|
|
context.logger.info("Received request to send \(event.count) messages: '\(event.message)'")
|
|
|
|
// Validate input
|
|
guard event.count > 0 && event.count <= 100 else {
|
|
let errorMessage = "Count must be between 1 and 100, got: \(event.count)"
|
|
context.logger.error("\(errorMessage)")
|
|
try await responseWriter.writeAndFinish(ByteBuffer(string: "Error: \(errorMessage)\n"))
|
|
return
|
|
}
|
|
|
|
// Stream the messages
|
|
for i in 1...event.count {
|
|
let response = "[\(Date().ISO8601Format())] Message \(i)/\(event.count): \(event.message)\n"
|
|
try await responseWriter.write(ByteBuffer(string: response))
|
|
|
|
// Optional delay between messages
|
|
if event.delay > 0 {
|
|
try await Task.sleep(for: .milliseconds(event.delay))
|
|
}
|
|
}
|
|
|
|
// Send completion message and finish the stream
|
|
let completionMessage = "✅ Successfully sent \(event.count) messages\n"
|
|
try await responseWriter.writeAndFinish(ByteBuffer(string: completionMessage))
|
|
|
|
// Optional: Do background work here after response is sent
|
|
context.logger.info("Background work: cleaning up resources and logging metrics")
|
|
|
|
// Simulate some background processing
|
|
try await Task.sleep(for: .milliseconds(100))
|
|
context.logger.info("Background work completed")
|
|
}
|
|
|
|
try await runtime.run()
|