@@ -327,7 +327,7 @@ public actor ServiceGroup: Sendable {
327
327
services [ index] = nil
328
328
do {
329
329
try await self . shutdownGracefully (
330
- services: services,
330
+ services: & services,
331
331
cancellationTimeoutTask: & cancellationTimeoutTask,
332
332
group: & group,
333
333
gracefulShutdownManagers: gracefulShutdownManagers
@@ -380,7 +380,7 @@ public actor ServiceGroup: Sendable {
380
380
381
381
do {
382
382
try await self . shutdownGracefully (
383
- services: services,
383
+ services: & services,
384
384
cancellationTimeoutTask: & cancellationTimeoutTask,
385
385
group: & group,
386
386
gracefulShutdownManagers: gracefulShutdownManagers
@@ -421,7 +421,7 @@ public actor ServiceGroup: Sendable {
421
421
)
422
422
do {
423
423
try await self . shutdownGracefully (
424
- services: services,
424
+ services: & services,
425
425
cancellationTimeoutTask: & cancellationTimeoutTask,
426
426
group: & group,
427
427
gracefulShutdownManagers: gracefulShutdownManagers
@@ -448,7 +448,7 @@ public actor ServiceGroup: Sendable {
448
448
449
449
do {
450
450
try await self . shutdownGracefully (
451
- services: services,
451
+ services: & services,
452
452
cancellationTimeoutTask: & cancellationTimeoutTask,
453
453
group: & group,
454
454
gracefulShutdownManagers: gracefulShutdownManagers
@@ -489,7 +489,7 @@ public actor ServiceGroup: Sendable {
489
489
}
490
490
491
491
private func shutdownGracefully(
492
- services: [ ServiceGroupConfiguration . ServiceConfiguration ? ] ,
492
+ services: inout [ ServiceGroupConfiguration . ServiceConfiguration ? ] ,
493
493
cancellationTimeoutTask: inout Task < Void , Never > ? ,
494
494
group: inout ThrowingTaskGroup < ChildTaskResult , Error > ,
495
495
gracefulShutdownManagers: [ GracefulShutdownManager ]
@@ -519,7 +519,7 @@ public actor ServiceGroup: Sendable {
519
519
self . logger. debug (
520
520
" Service already finished. Skipping shutdown "
521
521
)
522
- continue
522
+ continue gracefulShutdownLoop
523
523
}
524
524
self . logger. debug (
525
525
" Triggering graceful shutdown for service " ,
@@ -533,6 +533,7 @@ public actor ServiceGroup: Sendable {
533
533
while let result = try await group. next ( ) {
534
534
switch result {
535
535
case . serviceFinished( let service, let index) :
536
+ services [ index] = nil
536
537
if group. isCancelled {
537
538
// The group is cancelled and we expect all services to finish
538
539
continue gracefulShutdownLoop
@@ -561,7 +562,8 @@ public actor ServiceGroup: Sendable {
561
562
throw ServiceGroupError . serviceFinishedUnexpectedly ( )
562
563
}
563
564
564
- case . serviceThrew( let service, _, let serviceError) :
565
+ case . serviceThrew( let service, let index, let serviceError) :
566
+ services [ index] = nil
565
567
switch service. failureTerminationBehavior. behavior {
566
568
case . cancelGroup:
567
569
self . logger. debug (
@@ -575,32 +577,58 @@ public actor ServiceGroup: Sendable {
575
577
throw serviceError
576
578
577
579
case . gracefullyShutdownGroup:
578
- self . logger. debug (
579
- " Service threw error during graceful shutdown. " ,
580
- metadata: [
581
- self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
582
- self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
583
- ]
584
- )
585
-
586
580
if error == nil {
587
581
error = serviceError
588
582
}
589
583
590
- // We can continue shutting down the next service now
591
- continue gracefulShutdownLoop
584
+ if index == gracefulShutdownIndex {
585
+ // The service that we were shutting down right now threw. Since it's failure
586
+ // behaviour is to shutdown the group we can continue
587
+ self . logger. debug (
588
+ " The service that we were shutting down threw. Continuing with the next one. " ,
589
+ metadata: [
590
+ self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
591
+ self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
592
+ ]
593
+ )
594
+ continue gracefulShutdownLoop
595
+ } else {
596
+ // Another service threw while we were waiting for a shutdown
597
+ // We have to continue the iterating the task group's result
598
+ self . logger. debug (
599
+ " Another service than the service that we were shutting down threw. Continuing with the next one. " ,
600
+ metadata: [
601
+ self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
602
+ self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
603
+ ]
604
+ )
605
+ break
606
+ }
592
607
593
608
case . ignore:
594
- self . logger. debug (
595
- " Service threw error during graceful shutdown. " ,
596
- metadata: [
597
- self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
598
- self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
599
- ]
600
- )
601
-
602
- // We can continue shutting down the next service now
603
- continue gracefulShutdownLoop
609
+ if index == gracefulShutdownIndex {
610
+ // The service that we were shutting down right now threw. Since it's failure
611
+ // behaviour is to shutdown the group we can continue
612
+ self . logger. debug (
613
+ " The service that we were shutting down threw. Continuing with the next one. " ,
614
+ metadata: [
615
+ self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
616
+ self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
617
+ ]
618
+ )
619
+ continue gracefulShutdownLoop
620
+ } else {
621
+ // Another service threw while we were waiting for a shutdown
622
+ // We have to continue the iterating the task group's result
623
+ self . logger. debug (
624
+ " Another service than the service that we were shutting down threw. Continuing with the next one. " ,
625
+ metadata: [
626
+ self . loggingConfiguration. keys. serviceKey: " \( service. service) " ,
627
+ self . loggingConfiguration. keys. errorKey: " \( serviceError) " ,
628
+ ]
629
+ )
630
+ break
631
+ }
604
632
}
605
633
606
634
case . signalCaught( let signal) :
@@ -635,7 +663,8 @@ public actor ServiceGroup: Sendable {
635
663
636
664
case . signalSequenceFinished, . gracefulShutdownCaught, . gracefulShutdownFinished:
637
665
// We just have to tolerate this since signals and parent graceful shutdowns downs can race.
638
- // We are going to continue the
666
+ // We are going to continue the result loop since we have to wait for our service
667
+ // to finish.
639
668
break
640
669
}
641
670
}
0 commit comments