@@ -75,6 +75,53 @@ struct LambdaRuntimeTests {
75
75
taskGroup. cancelAll ( )
76
76
}
77
77
}
78
+ @Test ( " run() must be cancellable " )
79
+ func testLambdaRuntimeCancellable( ) async throws {
80
+
81
+ let logger = Logger ( label: " LambdaRuntimeTests.RuntimeCancellable " )
82
+ // create a runtime
83
+ let runtime = LambdaRuntime (
84
+ handler: MockHandler ( ) ,
85
+ eventLoop: Lambda . defaultEventLoop,
86
+ logger: logger
87
+ )
88
+
89
+ // Running the runtime with structured concurrency
90
+ // Task group returns when all tasks are completed.
91
+ // Even cancelled tasks must cooperatlivly complete
92
+ await #expect( throws: Never . self) {
93
+ try await withThrowingTaskGroup ( of: Void . self) { taskGroup in
94
+ taskGroup. addTask {
95
+ logger. trace ( " --- launching runtime ---- " )
96
+ try await runtime. run ( )
97
+ }
98
+
99
+ // Add a timeout task to the group
100
+ taskGroup. addTask {
101
+ logger. trace ( " --- launching timeout task ---- " )
102
+ try await Task . sleep ( for: . seconds( 5 ) )
103
+ if Task . isCancelled { return }
104
+ logger. trace ( " --- throwing timeout error ---- " )
105
+ throw TestError . timeout // Fail the test if the timeout triggers
106
+ }
107
+
108
+ do {
109
+ // Wait for the runtime to start
110
+ logger. trace ( " --- waiting for runtime to start ---- " )
111
+ try await Task . sleep ( for: . seconds( 1 ) )
112
+
113
+ // Cancel all tasks, this should not throw an error
114
+ // and should allow the runtime to complete gracefully
115
+ logger. trace ( " --- cancel all tasks ---- " )
116
+ taskGroup. cancelAll ( ) // Cancel all tasks
117
+ } catch {
118
+ logger. error ( " --- catch an error: \( error) " )
119
+ throw error // Propagate the error to fail the test
120
+ }
121
+ }
122
+ }
123
+
124
+ }
78
125
}
79
126
80
127
struct MockHandler : StreamingLambdaHandler {
@@ -86,3 +133,15 @@ struct MockHandler: StreamingLambdaHandler {
86
133
87
134
}
88
135
}
136
+
137
+ // Define a custom error for timeout
138
+ enum TestError : Error , CustomStringConvertible {
139
+ case timeout
140
+
141
+ var description : String {
142
+ switch self {
143
+ case . timeout:
144
+ return " Test timed out waiting for the task to complete. "
145
+ }
146
+ }
147
+ }
0 commit comments