Skip to content

Commit

Permalink
Change Lambda.Context from class to struct (#217)
Browse files Browse the repository at this point in the history
Motivation: Lambda.Context is currently a class that only holds values. For this reason it should be a value type itself.

Changes: Lambda.Context is now a struct, that is backed by a CoW storage class, to ensure performance remains high.
  • Loading branch information
jareyesda authored Aug 11, 2021
1 parent a9e15b1 commit 774bbf1
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 27 deletions.
100 changes: 74 additions & 26 deletions Sources/AWSLambdaRuntimeCore/LambdaContext.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,40 +49,94 @@ extension Lambda {
extension Lambda {
/// Lambda runtime context.
/// The Lambda runtime generates and passes the `Context` to the Lambda handler as an argument.
public final class Context: CustomDebugStringConvertible {
public struct Context: CustomDebugStringConvertible {
final class _Storage {
var requestID: String
var traceID: String
var invokedFunctionARN: String
var deadline: DispatchWallTime
var cognitoIdentity: String?
var clientContext: String?
var logger: Logger
var eventLoop: EventLoop
var allocator: ByteBufferAllocator

init(
requestID: String,
traceID: String,
invokedFunctionARN: String,
deadline: DispatchWallTime,
cognitoIdentity: String?,
clientContext: String?,
logger: Logger,
eventLoop: EventLoop,
allocator: ByteBufferAllocator
) {
self.requestID = requestID
self.traceID = traceID
self.invokedFunctionARN = invokedFunctionARN
self.deadline = deadline
self.cognitoIdentity = cognitoIdentity
self.clientContext = clientContext
self.logger = logger
self.eventLoop = eventLoop
self.allocator = allocator
}
}

private var storage: _Storage

/// The request ID, which identifies the request that triggered the function invocation.
public let requestID: String
public var requestID: String {
self.storage.requestID
}

/// The AWS X-Ray tracing header.
public let traceID: String
public var traceID: String {
self.storage.traceID
}

/// The ARN of the Lambda function, version, or alias that's specified in the invocation.
public let invokedFunctionARN: String
public var invokedFunctionARN: String {
self.storage.invokedFunctionARN
}

/// The timestamp that the function times out
public let deadline: DispatchWallTime
public var deadline: DispatchWallTime {
self.storage.deadline
}

/// For invocations from the AWS Mobile SDK, data about the Amazon Cognito identity provider.
public let cognitoIdentity: String?
public var cognitoIdentity: String? {
self.storage.cognitoIdentity
}

/// For invocations from the AWS Mobile SDK, data about the client application and device.
public let clientContext: String?
public var clientContext: String? {
self.storage.clientContext
}

/// `Logger` to log with
///
/// - note: The `LogLevel` can be configured using the `LOG_LEVEL` environment variable.
public let logger: Logger
public var logger: Logger {
self.storage.logger
}

/// The `EventLoop` the Lambda is executed on. Use this to schedule work with.
/// This is useful when implementing the `EventLoopLambdaHandler` protocol.
///
/// - note: The `EventLoop` is shared with the Lambda runtime engine and should be handled with extra care.
/// Most importantly the `EventLoop` must never be blocked.
public let eventLoop: EventLoop
public var eventLoop: EventLoop {
self.storage.eventLoop
}

/// `ByteBufferAllocator` to allocate `ByteBuffer`
/// This is useful when implementing `EventLoopLambdaHandler`
public let allocator: ByteBufferAllocator
public var allocator: ByteBufferAllocator {
self.storage.allocator
}

internal init(requestID: String,
traceID: String,
Expand All @@ -92,22 +146,16 @@ extension Lambda {
clientContext: String? = nil,
logger: Logger,
eventLoop: EventLoop,
allocator: ByteBufferAllocator)
{
self.requestID = requestID
self.traceID = traceID
self.invokedFunctionARN = invokedFunctionARN
self.cognitoIdentity = cognitoIdentity
self.clientContext = clientContext
self.deadline = deadline
// utility
self.eventLoop = eventLoop
self.allocator = allocator
// mutate logger with context
var logger = logger
logger[metadataKey: "awsRequestID"] = .string(requestID)
logger[metadataKey: "awsTraceID"] = .string(traceID)
self.logger = logger
allocator: ByteBufferAllocator) {
self.storage = _Storage(requestID: requestID,
traceID: traceID,
invokedFunctionARN: invokedFunctionARN,
deadline: deadline,
cognitoIdentity: cognitoIdentity,
clientContext: clientContext,
logger: logger,
eventLoop: eventLoop,
allocator: allocator)
}

public func getRemainingTime() -> TimeAmount {
Expand Down
2 changes: 1 addition & 1 deletion Sources/AWSLambdaRuntimeCore/LambdaRunner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ extension Lambda {
}

extension Lambda.Context {
fileprivate convenience init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Lambda.Invocation) {
init(logger: Logger, eventLoop: EventLoop, allocator: ByteBufferAllocator, invocation: Lambda.Invocation) {
self.init(requestID: invocation.requestID,
traceID: invocation.traceID,
invokedFunctionARN: invocation.invokedFunctionARN,
Expand Down

0 comments on commit 774bbf1

Please sign in to comment.