@@ -134,9 +134,11 @@ public final class ConnectionPool<
134
134
Connection: PooledConnection ,
135
135
ConnectionID: Hashable & Sendable ,
136
136
ConnectionIDGenerator: ConnectionIDGeneratorProtocol ,
137
+ ConnectionConfiguration: Equatable & Sendable ,
137
138
Request: ConnectionRequestProtocol ,
138
139
RequestID: Hashable & Sendable ,
139
140
KeepAliveBehavior: ConnectionKeepAliveBehavior ,
141
+ Executor: ConnectionPoolExecutor ,
140
142
ObservabilityDelegate: ConnectionPoolObservabilityDelegate ,
141
143
Clock: _Concurrency . Clock
142
144
> : Sendable where
@@ -148,14 +150,19 @@ public final class ConnectionPool<
148
150
ObservabilityDelegate. ConnectionID == ConnectionID ,
149
151
Clock. Duration == Duration
150
152
{
151
- public typealias ConnectionFactory = @Sendable ( ConnectionID , ConnectionPool < Connection , ConnectionID , ConnectionIDGenerator , Request , RequestID , KeepAliveBehavior , ObservabilityDelegate , Clock > ) async throws -> ConnectionAndMetadata < Connection >
153
+ public typealias ConnectionFactory = @Sendable ( ConnectionID , ConnectionConfiguration , ConnectionPool < Connection , ConnectionID , ConnectionIDGenerator , ConnectionConfiguration , Request , RequestID , KeepAliveBehavior , Executor , ObservabilityDelegate , Clock > ) async throws -> ConnectionAndMetadata < Connection >
152
154
153
155
@usableFromInline
154
156
typealias StateMachine = PoolStateMachine < Connection , ConnectionIDGenerator , ConnectionID , Request , Request . ID , CheckedContinuation < Void , Never > >
155
157
156
158
@usableFromInline
157
159
let factory : ConnectionFactory
158
160
161
+ public let executor : Executor
162
+
163
+ @usableFromInline
164
+ let connectionConfiguration : ConnectionConfiguration
165
+
159
166
@usableFromInline
160
167
let keepAliveBehavior : KeepAliveBehavior
161
168
@@ -188,18 +195,22 @@ public final class ConnectionPool<
188
195
189
196
public init (
190
197
configuration: ConnectionPoolConfiguration ,
198
+ connectionConfiguration: ConnectionConfiguration ,
191
199
idGenerator: ConnectionIDGenerator ,
192
200
requestType: Request . Type ,
193
201
keepAliveBehavior: KeepAliveBehavior ,
202
+ executor: Executor ,
194
203
observabilityDelegate: ObservabilityDelegate ,
195
204
clock: Clock ,
196
205
connectionFactory: @escaping ConnectionFactory
197
206
) {
207
+ self . executor = executor
198
208
self . clock = clock
199
209
self . factory = connectionFactory
200
210
self . keepAliveBehavior = keepAliveBehavior
201
211
self . observabilityDelegate = observabilityDelegate
202
212
self . configuration = configuration
213
+ self . connectionConfiguration = connectionConfiguration
203
214
var stateMachine = StateMachine (
204
215
configuration: . init( configuration, keepAliveBehavior: keepAliveBehavior) ,
205
216
generator: idGenerator,
@@ -271,6 +282,13 @@ public final class ConnectionPool<
271
282
}
272
283
}
273
284
285
+ @inlinable
286
+ public func updateConfiguration( _ configuration: ConnectionConfiguration , forceReconnection: Bool ) {
287
+ // TODO: Implement connection will close correctly
288
+ // If the forceReconnection flag is set, we should gracefully close the connection once they
289
+ // are returned the next time.
290
+ }
291
+
274
292
@inlinable
275
293
public func run( ) async {
276
294
await withTaskCancellationHandler {
@@ -419,11 +437,11 @@ public final class ConnectionPool<
419
437
420
438
@inlinable
421
439
/*private*/ func makeConnection( for request: StateMachine . ConnectionRequest , in taskGroup: inout some TaskGroupProtocol ) {
422
- taskGroup . addTask_ {
440
+ self . addTask ( into : & taskGroup ) {
423
441
self . observabilityDelegate. startedConnecting ( id: request. connectionID)
424
442
425
443
do {
426
- let bundle = try await self . factory ( request. connectionID, self )
444
+ let bundle = try await self . factory ( request. connectionID, self . connectionConfiguration , self )
427
445
self . connectionEstablished ( bundle)
428
446
429
447
// after the connection has been established, we keep the task open. This ensures
@@ -468,7 +486,7 @@ public final class ConnectionPool<
468
486
/*private*/ func runKeepAlive( _ connection: Connection , in taskGroup: inout some TaskGroupProtocol ) {
469
487
self . observabilityDelegate. keepAliveTriggered ( id: connection. id)
470
488
471
- taskGroup . addTask_ {
489
+ self . addTask ( into : & taskGroup ) {
472
490
do {
473
491
try await self . keepAliveBehavior. runKeepAlive ( for: connection)
474
492
@@ -502,8 +520,8 @@ public final class ConnectionPool<
502
520
}
503
521
504
522
@inlinable
505
- /*private*/ func runTimer( _ timer: StateMachine . Timer , in poolGroup : inout some TaskGroupProtocol ) {
506
- poolGroup . addTask_ { ( ) async -> ( ) in
523
+ /*private*/ func runTimer( _ timer: StateMachine . Timer , in taskGroup : inout some TaskGroupProtocol ) {
524
+ self . addTask ( into : & taskGroup ) { ( ) async -> ( ) in
507
525
await withTaskGroup ( of: TimerRunResult . self, returning: Void . self) { taskGroup in
508
526
taskGroup. addTask {
509
527
do {
@@ -554,6 +572,15 @@ public final class ConnectionPool<
554
572
token. resume ( )
555
573
}
556
574
}
575
+
576
+ @inlinable
577
+ func addTask( into taskGroup: inout some TaskGroupProtocol , operation: @escaping @Sendable ( ) async -> Void ) {
578
+ if #available( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , * ) , let executor = self . executor as? TaskExecutor {
579
+ taskGroup. addTask_ ( executorPreference: executor, operation: operation)
580
+ } else {
581
+ taskGroup. addTask_ ( operation: operation)
582
+ }
583
+ }
557
584
}
558
585
559
586
@available ( macOS 13 . 0 , iOS 16 . 0 , tvOS 16 . 0 , watchOS 9 . 0 , * )
@@ -573,6 +600,9 @@ protocol TaskGroupProtocol {
573
600
// under exactly this name and others have different attributes. So let's pick
574
601
// a name that doesn't clash anywhere and implement it using the standard `addTask`.
575
602
mutating func addTask_( operation: @escaping @Sendable ( ) async -> Void )
603
+
604
+ @available ( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , * )
605
+ mutating func addTask_( executorPreference: ( ( any TaskExecutor ) ? ) , operation: @escaping @Sendable ( ) async -> Void )
576
606
}
577
607
578
608
@available ( macOS 14 . 0 , iOS 17 . 0 , tvOS 17 . 0 , watchOS 10 . 0 , * )
@@ -581,11 +611,23 @@ extension DiscardingTaskGroup: TaskGroupProtocol {
581
611
mutating func addTask_( operation: @escaping @Sendable ( ) async -> Void ) {
582
612
self . addTask ( priority: nil , operation: operation)
583
613
}
614
+
615
+ @available ( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , * )
616
+ @inlinable
617
+ mutating func addTask_( executorPreference: ( any TaskExecutor ) ? , operation: @escaping @Sendable ( ) async -> Void ) {
618
+ self . addTask ( executorPreference: executorPreference, operation: operation)
619
+ }
584
620
}
585
621
586
622
extension TaskGroup < Void > : TaskGroupProtocol {
587
623
@inlinable
588
624
mutating func addTask_( operation: @escaping @Sendable ( ) async -> Void ) {
589
625
self . addTask ( priority: nil , operation: operation)
590
626
}
627
+
628
+ @available ( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , * )
629
+ @inlinable
630
+ mutating func addTask_( executorPreference: ( any TaskExecutor ) ? , operation: @escaping @Sendable ( ) async -> Void ) {
631
+ self . addTask ( executorPreference: executorPreference, operation: operation)
632
+ }
591
633
}
0 commit comments