16
16
import DequeModule
17
17
import Dispatch
18
18
import Logging
19
- import NIOConcurrencyHelpers
20
19
import NIOCore
21
20
import NIOHTTP1
22
21
import NIOPosix
@@ -183,21 +182,29 @@ private struct LambdaHTTPServer {
183
182
}
184
183
}
185
184
186
- let task1 = await group. next ( ) !
185
+ // Now that the local HTTP server and LambdaHandler tasks are started, wait for the
186
+ // first of the two that will terminate.
187
+ // When the first task terminates, cancel the group and collect the result of the
188
+ // second task.
189
+
190
+ // collect and return the result of the LambdaHandler
191
+ let serverOrHandlerResult1 = await group. next ( ) !
187
192
group. cancelAll ( )
188
- let task2 = await group. next ( ) !
189
193
190
- switch task1 {
194
+ switch serverOrHandlerResult1 {
191
195
case . closureResult( let result) :
192
196
return result
193
197
194
- case . serverReturned:
195
- switch task2 {
198
+ case . serverReturned( let result) :
199
+ logger. error ( " Server shutdown before closure completed " , metadata: [
200
+ " error " : " \( result. maybeError != nil ? " \( result. maybeError!) " : " none " ) "
201
+ ] )
202
+ switch await group. next ( ) ! {
196
203
case . closureResult( let result) :
197
204
return result
198
205
199
206
case . serverReturned:
200
- fatalError ( )
207
+ fatalError ( " Only one task is a server, and only one can return `serverReturned` " )
201
208
}
202
209
}
203
210
}
@@ -404,34 +411,26 @@ private struct LambdaHTTPServer {
404
411
private final class Pool < T> : AsyncSequence , AsyncIteratorProtocol , Sendable where T: Sendable {
405
412
typealias Element = T
406
413
407
- struct State {
408
- enum State {
409
- case buffer( Deque < T > )
410
- case continuation( CheckedContinuation < T , any Error > ? )
411
- }
412
-
413
- var state : State
414
-
415
- init ( ) {
416
- self . state = . buffer( [ ] )
417
- }
414
+ enum State : ~ Copyable {
415
+ case buffer( Deque < T > )
416
+ case continuation( CheckedContinuation < T , any Error > ? )
418
417
}
419
418
420
- private let lock = Mutex < State > ( . init ( ) )
419
+ private let lock = Mutex < State > ( . buffer ( [ ] ) )
421
420
422
421
/// enqueue an element, or give it back immediately to the iterator if it is waiting for an element
423
422
public func push( _ invocation: T ) async {
424
423
// if the iterator is waiting for an element, give it to it
425
424
// otherwise, enqueue the element
426
425
let maybeContinuation = self . lock. withLock { state -> CheckedContinuation < T , any Error > ? in
427
- switch state . state {
426
+ switch consume state {
428
427
case . continuation( let continuation) :
429
- state. state = . buffer( [ ] )
428
+ state = . buffer( [ ] )
430
429
return continuation
431
430
432
431
case . buffer( var buffer) :
433
432
buffer. append ( invocation)
434
- state. state = . buffer( buffer)
433
+ state = . buffer( buffer)
435
434
return nil
436
435
}
437
436
}
@@ -447,18 +446,18 @@ private struct LambdaHTTPServer {
447
446
448
447
return try await withCheckedThrowingContinuation { ( continuation: CheckedContinuation < T , any Error > ) in
449
448
let nextAction = self . lock. withLock { state -> T ? in
450
- switch state . state {
449
+ switch consume state {
451
450
case . buffer( var buffer) :
452
451
if let first = buffer. popFirst ( ) {
453
- state. state = . buffer( buffer)
452
+ state = . buffer( buffer)
454
453
return first
455
454
} else {
456
- state. state = . continuation( continuation)
455
+ state = . continuation( continuation)
457
456
return nil
458
457
}
459
458
460
459
case . continuation:
461
- fatalError ( " Concurrent invocations to next(). This is illigal . " )
460
+ fatalError ( " Concurrent invocations to next(). This is illegal . " )
462
461
}
463
462
}
464
463
@@ -509,3 +508,14 @@ private struct LambdaHTTPServer {
509
508
}
510
509
}
511
510
#endif
511
+
512
+ extension Result {
513
+ var maybeError : Failure ? {
514
+ switch self {
515
+ case . success:
516
+ return nil
517
+ case . failure( let error) :
518
+ return error
519
+ }
520
+ }
521
+ }
0 commit comments