@@ -16,6 +16,13 @@ public struct RedisConfiguration: Sendable {
1616 public var tlsConfiguration : TLSConfiguration ?
1717 public var tlsHostname : String ?
1818
19+ internal var deferredHostname : String ?
20+ internal var deferredPort : Int ?
21+
22+ public var hasUnresolvedHostname : Bool {
23+ return deferredHostname != nil
24+ }
25+
1926 public struct PoolOptions : Sendable {
2027 public var maximumConnectionCount : RedisConnectionPoolSize
2128 public var minimumConnectionCount : Int
@@ -83,14 +90,22 @@ public struct RedisConfiguration: Sendable {
8390 ) throws {
8491 if database != nil && database! < 0 { throw ValidationError . outOfBoundsDatabaseID }
8592
86- try self . init (
87- serverAddresses: [ . makeAddressResolvingHost( hostname, port: port) ] ,
88- password: password,
89- tlsConfiguration: tlsConfiguration,
90- tlsHostname: hostname,
91- database: database,
92- pool: pool
93- )
93+ do {
94+ let resolvedAdress = try SocketAddress . makeAddressResolvingHost ( hostname, port: port)
95+ self . serverAddresses = [ resolvedAdress]
96+ self . deferredHostname = nil
97+ self . deferredPort = nil
98+ } catch {
99+ self . serverAddresses = [ ]
100+ self . deferredHostname = hostname
101+ self . deferredPort = port
102+ }
103+
104+ self . password = password
105+ self . tlsConfiguration = tlsConfiguration
106+ self . tlsHostname = hostname
107+ self . database = database
108+ self . pool = pool
94109 }
95110
96111 public init (
@@ -102,18 +117,48 @@ public struct RedisConfiguration: Sendable {
102117 pool: PoolOptions = . init( )
103118 ) throws {
104119 self . serverAddresses = serverAddresses
120+ self . deferredHostname = nil
121+ self . deferredPort = nil
105122 self . password = password
106123 self . tlsConfiguration = tlsConfiguration
107124 self . tlsHostname = tlsHostname
108125 self . database = database
109126 self . pool = pool
110127 }
128+
129+ /// Attempts to resolve any pending hostname resolution
130+ /// - Returns: new configuration with resolved addresses, or throws if resolution fails
131+ public func resolveServerAddresses( ) throws -> RedisConfiguration {
132+ guard let hostname = deferredHostname, let port = deferredPort else {
133+ return self
134+ }
135+
136+ var resolved = self
137+ let resolvedAddress = try SocketAddress . makeAddressResolvingHost ( hostname, port: port)
138+ resolved. serverAddresses = [ resolvedAddress]
139+ resolved. deferredHostname = nil
140+ resolved. deferredPort = nil
141+ return resolved
142+ }
111143}
112144
113145extension RedisConnectionPool . Configuration {
114146 internal init ( _ config: RedisConfiguration , defaultLogger: Logger , customClient: ClientBootstrap ? ) {
147+ // Handle deferred hostname resolution at pool creation time
148+ var addresses = config. serverAddresses
149+
150+ if let hostname = config. deferredHostname, let port = config. deferredPort {
151+ do {
152+ let resolvedAddress = try SocketAddress . makeAddressResolvingHost ( hostname, port: port)
153+ addresses = [ resolvedAddress]
154+ } catch {
155+ defaultLogger. notice ( " Hostname ' \( hostname) ' could not be resolved at pool creation time: \( error) . Redis connections will fail until hostname becomes resolvable. " )
156+ // Placeholder address so Redis operations fail gracefully
157+ addresses = [ try ! SocketAddress . makeAddressResolvingHost ( " 0.0.0.0 " , port: 1 ) ]
158+ }
159+ }
115160 self . init (
116- initialServerConnectionAddresses: config . serverAddresses ,
161+ initialServerConnectionAddresses: addresses ,
117162 maximumConnectionCount: config. pool. maximumConnectionCount,
118163 connectionFactoryConfiguration: . init(
119164 connectionInitialDatabase: config. database,
0 commit comments