Skip to content

Commit 41e8f86

Browse files
nilanshu-sharmaNilanshu Sharma
andauthored
Add Support for Numbered Databases (#259)
Adding support for numbered databases --------- Signed-off-by: Nilanshu Sharma <[email protected]> Co-authored-by: Nilanshu Sharma <[email protected]>
1 parent 6679b40 commit 41e8f86

File tree

5 files changed

+61
-4
lines changed

5 files changed

+61
-4
lines changed

Sources/Valkey/Connection/ValkeyChannelHandler.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ final class ValkeyChannelHandler: ChannelInboundHandler {
5858
let blockingCommandTimeout: TimeAmount
5959
let clientName: String?
6060
let readOnly: Bool
61+
let databaseNumber: Int
6162
}
6263
@usableFromInline
6364
struct PendingCommand {
@@ -292,6 +293,13 @@ final class ValkeyChannelHandler: ChannelInboundHandler {
292293
helloCommand.encode(into: &self.encoder)
293294
clientInfoLibName.encode(into: &self.encoder)
294295
clientInfoLibVersion.encode(into: &self.encoder)
296+
297+
// Select DB if needed
298+
if self.configuration.databaseNumber > 0 {
299+
numberOfPendingCommands += 1
300+
SELECT(index: self.configuration.databaseNumber).encode(into: &self.encoder)
301+
}
302+
295303
if self.configuration.readOnly {
296304
numberOfPendingCommands += 1
297305
READONLY().encode(into: &self.encoder)
@@ -539,7 +547,8 @@ extension ValkeyChannelHandler.Configuration {
539547
commandTimeout: .init(other.commandTimeout),
540548
blockingCommandTimeout: .init(other.blockingCommandTimeout),
541549
clientName: other.clientName,
542-
readOnly: other.readOnly
550+
readOnly: other.readOnly,
551+
databaseNumber: other.databaseNumber
543552
)
544553
}
545554
}

Sources/Valkey/Connection/ValkeyConnectionConfiguration.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ public struct ValkeyConnectionConfiguration: Sendable {
121121
/// Readonly connections can run readonly commands on replica nodes
122122
public var readOnly: Bool
123123

124+
/// The number of Valkey Database
125+
public var databaseNumber: Int = 0
126+
124127
#if DistributedTracingSupport
125128
/// The distributed tracing configuration to use for this connection.
126129
/// Defaults to using the globally bootstrapped tracer with OpenTelemetry semantic conventions.
@@ -139,20 +142,23 @@ public struct ValkeyConnectionConfiguration: Sendable {
139142
/// - tls: TLS configuration for secure connections. Defaults to `.disable` for unencrypted connections.
140143
/// - clientName: Optional name to identify this client connection on the server. Defaults to `nil`.
141144
/// - readOnly: Is the connection a readonly connection
145+
/// - databaseNumber: Database Number to use for the connection
142146
public init(
143147
authentication: Authentication? = nil,
144148
commandTimeout: Duration = .seconds(30),
145149
blockingCommandTimeout: Duration = .seconds(120),
146150
tls: TLS = .disable,
147151
clientName: String? = nil,
148-
readOnly: Bool = false
152+
readOnly: Bool = false,
153+
databaseNumber: Int = 0
149154
) {
150155
self.authentication = authentication
151156
self.commandTimeout = commandTimeout
152157
self.blockingCommandTimeout = blockingCommandTimeout
153158
self.tls = tls
154159
self.clientName = clientName
155160
self.readOnly = readOnly
161+
self.databaseNumber = databaseNumber
156162
}
157163
}
158164

Sources/Valkey/Connection/ValkeyConnectionFactory.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ package final class ValkeyConnectionFactory: Sendable {
112112
blockingCommandTimeout: self.configuration.blockingCommandTimeout,
113113
tls: tls,
114114
clientName: nil,
115-
readOnly: readOnly
115+
readOnly: readOnly,
116+
databaseNumber: self.configuration.databaseNumber
116117
)
117118

118119
#if DistributedTracingSupport

Sources/Valkey/ValkeyClientConfiguration.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ public struct ValkeyClientConfiguration: Sendable {
171171
/// The TLS to use for the Valkey connection.
172172
public var tls: TLS
173173

174+
/// Database Number to use for the Valkey Connection
175+
public var databaseNumber: Int = 0
176+
174177
#if DistributedTracingSupport
175178
/// The distributed tracing configuration to use for the Valkey connection.
176179
/// Defaults to using the globally bootstrapped tracer with OpenTelemetry semantic conventions.
@@ -187,14 +190,16 @@ public struct ValkeyClientConfiguration: Sendable {
187190
/// - commandTimeout: The timeout for a connection response.
188191
/// - blockingCommandTimeout: The timeout for a blocking command response.
189192
/// - tls: The TLS configuration.
193+
/// - databaseNumber: The Valkey Database number.
190194
public init(
191195
authentication: Authentication? = nil,
192196
connectionPool: ConnectionPool = .init(),
193197
keepAliveBehavior: KeepAliveBehavior = .init(),
194198
retryParameters: RetryParameters = .init(),
195199
commandTimeout: Duration = .seconds(30),
196200
blockingCommandTimeout: Duration = .seconds(120),
197-
tls: TLS = .disable
201+
tls: TLS = .disable,
202+
databaseNumber: Int = 0
198203
) {
199204
self.authentication = authentication
200205
self.connectionPool = connectionPool
@@ -203,5 +208,6 @@ public struct ValkeyClientConfiguration: Sendable {
203208
self.commandTimeout = commandTimeout
204209
self.blockingCommandTimeout = blockingCommandTimeout
205210
self.tls = tls
211+
self.databaseNumber = databaseNumber
206212
}
207213
}

Tests/IntegrationTests/ClientIntegrationTests.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,4 +592,39 @@ struct ClientIntegratedTests {
592592
#expect(clients.firstRange(of: "lib-ver=\(valkeySwiftLibraryVersion)") != nil)
593593
}
594594
}
595+
596+
@Test
597+
@available(valkeySwift 1.0, *)
598+
func testMultipleDB() async throws {
599+
var logger = Logger(label: "Valkey")
600+
logger.logLevel = .debug
601+
// Test all default enabled databases in range {0,15}
602+
for dbNum in 0...15 {
603+
let clientConfig: ValkeyClientConfiguration = .init(databaseNumber: dbNum)
604+
try await withValkeyConnection(.hostname(valkeyHostname, port: 6379), configuration: clientConfig, logger: logger) { connection in
605+
// Verify ClientInfo contains dbNum
606+
let clientInfo = String(buffer: try await connection.clientInfo())
607+
#expect(clientInfo.contains("db=\(dbNum)"))
608+
609+
// Verify via setting and getting keys on all the DBs
610+
let key = "key-\(dbNum)"
611+
let value = "value-\(dbNum)"
612+
try await connection.set(ValkeyKey(key), value: value)
613+
let response = try await connection.get(ValkeyKey(key)).map { String(buffer: $0) }
614+
#expect(response == value)
615+
616+
// Verify key belonging to other DBs don't exist in this DB
617+
for otherDbNum in 0...15 {
618+
let otherKey = "key-\(otherDbNum)"
619+
if otherDbNum == dbNum { continue }
620+
let otherResponse = try await connection.get(ValkeyKey(otherKey)).map { String(buffer: $0) }
621+
#expect(otherResponse == nil)
622+
}
623+
624+
let delCount = try await connection.del(keys: [ValkeyKey(key)])
625+
#expect(delCount == 1)
626+
}
627+
}
628+
}
629+
595630
}

0 commit comments

Comments
 (0)