@@ -28,6 +28,7 @@ extension Transaction {
28
28
private enum State {
29
29
case initialized( CheckedContinuation < HTTPClientResponse , Error > )
30
30
case queued( CheckedContinuation < HTTPClientResponse , Error > , HTTPRequestScheduler )
31
+ case deadlineExceededWhileQueued( CheckedContinuation < HTTPClientResponse , Error > )
31
32
case executing( ExecutionContext , RequestStreamState , ResponseStreamState )
32
33
case finished( error: Error ? , HTTPClientResponse . Body . IteratorStream . ID ? )
33
34
}
@@ -105,7 +106,20 @@ extension Transaction {
105
106
case . queued( let continuation, let scheduler) :
106
107
self . state = . finished( error: error, nil )
107
108
return . failResponseHead( continuation, error, scheduler, nil , bodyStreamContinuation: nil )
108
-
109
+ case . deadlineExceededWhileQueued( let continuation) :
110
+ let realError : Error = {
111
+ if ( error as? HTTPClientError ) == . cancelled {
112
+ /// if we just get a `HTTPClientError.cancelled` we can use the original cancellation reason
113
+ /// to give a more descriptive error to the user.
114
+ return HTTPClientError . deadlineExceeded
115
+ } else {
116
+ /// otherwise we already had an intermediate connection error which we should present to the user instead
117
+ return error
118
+ }
119
+ } ( )
120
+
121
+ self . state = . finished( error: realError, nil )
122
+ return . failResponseHead( continuation, realError, nil , nil , bodyStreamContinuation: nil )
109
123
case . executing( let context, let requestStreamState, . waitingForResponseHead) :
110
124
switch requestStreamState {
111
125
case . paused( continuation: . some( let continuation) ) :
@@ -178,6 +192,7 @@ extension Transaction {
178
192
179
193
enum StartExecutionAction {
180
194
case cancel( HTTPRequestExecutor )
195
+ case cancelAndFail( HTTPRequestExecutor , CheckedContinuation < HTTPClientResponse , Error > , with: Error )
181
196
case none
182
197
}
183
198
@@ -191,6 +206,8 @@ extension Transaction {
191
206
)
192
207
self . state = . executing( context, . requestHeadSent, . waitingForResponseHead)
193
208
return . none
209
+ case . deadlineExceededWhileQueued( let continuation) :
210
+ return . cancelAndFail( executor, continuation, with: HTTPClientError . deadlineExceeded)
194
211
195
212
case . finished( error: . some, . none) :
196
213
return . cancel( executor)
@@ -210,7 +227,7 @@ extension Transaction {
210
227
211
228
mutating func resumeRequestBodyStream( ) -> ResumeProducingAction {
212
229
switch self . state {
213
- case . initialized, . queued:
230
+ case . initialized, . queued, . deadlineExceededWhileQueued :
214
231
preconditionFailure ( " Received a resumeBodyRequest on a request, that isn't executing. Invalid state: \( self . state) " )
215
232
216
233
case . executing( let context, . requestHeadSent, let responseState) :
@@ -246,6 +263,7 @@ extension Transaction {
246
263
switch self . state {
247
264
case . initialized,
248
265
. queued,
266
+ . deadlineExceededWhileQueued,
249
267
. executing( _, . requestHeadSent, _) :
250
268
preconditionFailure ( " A request stream can only be resumed, if the request was started " )
251
269
@@ -271,6 +289,7 @@ extension Transaction {
271
289
switch self . state {
272
290
case . initialized,
273
291
. queued,
292
+ . deadlineExceededWhileQueued,
274
293
. executing( _, . requestHeadSent, _) :
275
294
preconditionFailure ( " A request stream can only produce, if the request was started. Invalid state: \( self . state) " )
276
295
@@ -301,6 +320,7 @@ extension Transaction {
301
320
switch self . state {
302
321
case . initialized,
303
322
. queued,
323
+ . deadlineExceededWhileQueued,
304
324
. executing( _, . requestHeadSent, _) ,
305
325
. executing( _, . finished, _) :
306
326
preconditionFailure ( " A request stream can only produce, if the request was started. Invalid state: \( self . state) " )
@@ -334,6 +354,7 @@ extension Transaction {
334
354
switch self . state {
335
355
case . initialized,
336
356
. queued,
357
+ . deadlineExceededWhileQueued,
337
358
. executing( _, . finished, _) :
338
359
preconditionFailure ( " Invalid state: \( self . state) " )
339
360
@@ -372,6 +393,7 @@ extension Transaction {
372
393
switch self . state {
373
394
case . initialized,
374
395
. queued,
396
+ . deadlineExceededWhileQueued,
375
397
. executing( _, _, . waitingForResponseIterator) ,
376
398
. executing( _, _, . buffering) ,
377
399
. executing( _, _, . waitingForRemote) :
@@ -401,7 +423,7 @@ extension Transaction {
401
423
402
424
mutating func receiveResponseBodyParts( _ buffer: CircularBuffer < ByteBuffer > ) -> ReceiveResponsePartAction {
403
425
switch self . state {
404
- case . initialized, . queued:
426
+ case . initialized, . queued, . deadlineExceededWhileQueued :
405
427
preconditionFailure ( " Received a response body part, but request hasn't started yet. Invalid state: \( self . state) " )
406
428
407
429
case . executing( _, _, . waitingForResponseHead) :
@@ -457,6 +479,7 @@ extension Transaction {
457
479
switch self . state {
458
480
case . initialized,
459
481
. queued,
482
+ . deadlineExceededWhileQueued,
460
483
. executing( _, _, . waitingForResponseHead) :
461
484
preconditionFailure ( " Got notice about a deinited response, before we even received a response. Invalid state: \( self . state) " )
462
485
@@ -486,7 +509,7 @@ extension Transaction {
486
509
487
510
mutating func responseBodyIteratorDeinited( streamID: HTTPClientResponse . Body . IteratorStream . ID ) -> FailAction {
488
511
switch self . state {
489
- case . initialized, . queued, . executing( _, _, . waitingForResponseHead) :
512
+ case . initialized, . queued, . deadlineExceededWhileQueued , . executing( _, _, . waitingForResponseHead) :
490
513
preconditionFailure ( " Got notice about a deinited response body iterator, before we even received a response. Invalid state: \( self . state) " )
491
514
492
515
case . executing( _, _, . buffering( let registeredStreamID, _, next: _) ) ,
@@ -516,6 +539,7 @@ extension Transaction {
516
539
switch self . state {
517
540
case . initialized,
518
541
. queued,
542
+ . deadlineExceededWhileQueued,
519
543
. executing( _, _, . waitingForResponseHead) :
520
544
preconditionFailure ( " If we receive a response body, we must have received a head before " )
521
545
@@ -635,6 +659,7 @@ extension Transaction {
635
659
switch self . state {
636
660
case . initialized,
637
661
. queued,
662
+ . deadlineExceededWhileQueued,
638
663
. executing( _, _, . waitingForResponseHead) :
639
664
preconditionFailure ( " Received no response head, but received a response end. Invalid state: \( self . state) " )
640
665
@@ -677,6 +702,7 @@ extension Transaction {
677
702
678
703
enum DeadlineExceededAction {
679
704
case none
705
+ case cancelSchedulerOnly( scheduler: HTTPRequestScheduler )
680
706
/// fail response before head received. scheduler and executor are exclusive here.
681
707
case cancel(
682
708
requestContinuation: CheckedContinuation < HTTPClientResponse , Error > ,
@@ -699,14 +725,12 @@ extension Transaction {
699
725
)
700
726
701
727
case . queued( let continuation, let scheduler) :
702
- self . state = . finished( error: error, nil )
703
- return . cancel(
704
- requestContinuation: continuation,
705
- scheduler: scheduler,
706
- executor: nil ,
707
- bodyStreamContinuation: nil
728
+ self . state = . deadlineExceededWhileQueued( continuation)
729
+ return . cancelSchedulerOnly(
730
+ scheduler: scheduler
708
731
)
709
-
732
+ case . deadlineExceededWhileQueued:
733
+ return . none
710
734
case . executing( let context, let requestStreamState, . waitingForResponseHead) :
711
735
switch requestStreamState {
712
736
case . paused( continuation: . some( let continuation) ) :
0 commit comments