Skip to content

Commit b37ea0e

Browse files
committed
fix lost continuation
1 parent be4cb20 commit b37ea0e

File tree

3 files changed

+29
-24
lines changed

3 files changed

+29
-24
lines changed

Sources/AWSLambdaRuntime/Lambda.swift

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ public enum Lambda {
4242
do {
4343
while !Task.isCancelled {
4444

45-
guard let runtimeClient = runtimeClient as? LambdaRuntimeClient,
46-
await !runtimeClient.didLooseConnection else {
47-
logger.trace("Runtime client disconnected, exiting run loop")
48-
throw LambdaRuntimeError.init(code: .connectionToControlPlaneLost)
49-
}
50-
5145
logger.trace("Waiting for next invocation")
5246
let (invocation, writer) = try await runtimeClient.nextInvocation()
5347
logger[metadataKey: "aws-request-id"] = "\(invocation.metadata.requestID)"

Sources/AWSLambdaRuntime/LambdaRuntimeClient.swift

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,6 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
114114

115115
private var connectionState: ConnectionState = .disconnected
116116

117-
// adding this dynamic property because I can not give access to `connectionState` directly
118-
// because it is private, depending on multiple private and non-Sendable types
119-
// the only thing we need to know outside of this class is if the connection state is disconnected
120-
@usableFromInline
121-
var didLooseConnection: Bool {
122-
get {
123-
self.connectionState == .lostConnection
124-
}
125-
}
126-
127117
private var lambdaState: LambdaState = .idle(previousRequestID: nil)
128118
private var closingState: ClosingState = .notClosing
129119

@@ -146,7 +136,6 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
146136
result = .failure(error)
147137
}
148138
await runtime.close()
149-
150139
return try result.get()
151140
}
152141

@@ -182,22 +171,27 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
182171

183172
case .connected(let channel, _):
184173
channel.close(mode: .all, promise: nil)
174+
185175
case .lostConnection:
186-
// this should never happen.
187-
fatalError("Lost connection to Lambda service while closing the runtime client")
176+
continuation.resume()
188177
}
189178
}
190179
}
191180

192181
@usableFromInline
193182
func nextInvocation() async throws -> (Invocation, Writer) {
194183

195-
try await withTaskCancellationHandler {
184+
if self.connectionState == .lostConnection {
185+
throw LambdaRuntimeError(code: .connectionToControlPlaneLost)
186+
}
187+
188+
return try await withTaskCancellationHandler {
196189
switch self.lambdaState {
197190
case .idle:
198191
self.lambdaState = .waitingForNextInvocation
199192
let handler = try await self.makeOrGetConnection()
200193
let invocation = try await handler.nextInvocation()
194+
201195
guard case .waitingForNextInvocation = self.lambdaState else {
202196
fatalError("Invalid state: \(self.lambdaState)")
203197
}
@@ -312,7 +306,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
312306
case (.connecting(let array), .notClosing):
313307
self.connectionState = .disconnected
314308
for continuation in array {
315-
continuation.resume(throwing: LambdaRuntimeError(code: .lostConnectionToControlPlane))
309+
continuation.resume(throwing: LambdaRuntimeError(code: .connectionToControlPlaneLost))
316310
}
317311

318312
case (.connecting(let array), .closing(let continuation)):
@@ -326,6 +320,7 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
326320
case (.connected, .notClosing):
327321
self.connectionState = .disconnected
328322

323+
329324
case (.connected, .closing(let continuation)):
330325
self.connectionState = .disconnected
331326

@@ -398,13 +393,24 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
398393
)
399394
channel.closeFuture.whenComplete { result in
400395
self.assumeIsolated { runtimeClient in
396+
397+
// resume any pending continuation on the handler
398+
if case .connected(_ , let handler) = runtimeClient.connectionState {
399+
if case .connected(_ , let lambdaState) = handler.state {
400+
if case .waitingForNextInvocation(let continuation) = lambdaState {
401+
continuation.resume(throwing: LambdaRuntimeError(code: .connectionToControlPlaneLost))
402+
}
403+
}
404+
}
405+
406+
// close the channel
401407
runtimeClient.channelClosed(channel)
402408
runtimeClient.connectionState = .lostConnection
403409
}
404410
}
405411

406412
switch self.connectionState {
407-
case .disconnected, .connected, .lostConnection:
413+
case .disconnected, .connected:
408414
fatalError("Unexpected state: \(self.connectionState)")
409415

410416
case .connecting(let array):
@@ -416,11 +422,14 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
416422
}
417423
}
418424
return handler
425+
case .lostConnection:
426+
// this should never happen
427+
fatalError("Lost connection to Lambda service")
419428
}
420429
} catch {
421430

422431
switch self.connectionState {
423-
case .disconnected, .connected, .lostConnection:
432+
case .disconnected, .connected:
424433
fatalError("Unexpected state: \(self.connectionState)")
425434

426435
case .connecting(let array):
@@ -431,6 +440,9 @@ final actor LambdaRuntimeClient: LambdaRuntimeClientProtocol {
431440
}
432441
}
433442
throw error
443+
case .lostConnection:
444+
// this should never happen
445+
fatalError("Lost connection to Lambda service")
434446
}
435447
}
436448
}

Sources/AWSLambdaRuntime/LambdaRuntimeError.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ package struct LambdaRuntimeError: Error {
2525

2626
case writeAfterFinishHasBeenSent
2727
case finishAfterFinishHasBeenSent
28-
case lostConnectionToControlPlane
2928
case unexpectedStatusCodeForRequest
3029

3130
case nextInvocationMissingHeaderRequestID

0 commit comments

Comments
 (0)