Skip to content

Commit 54d37af

Browse files
committed
Update from PR comments
- Moved nodeSelection setting into it own function getNodeSelection - Added `cycleAllNode` - Renamed `ReadOnlyReplicaSelection` to `ReadOnlyCommandNodeSelection` Signed-off-by: Adam Fowler <[email protected]>
1 parent eb2b8bf commit 54d37af

File tree

3 files changed

+44
-44
lines changed

3 files changed

+44
-44
lines changed

Sources/Valkey/Cluster/ValkeyClusterClient.swift

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,7 @@ public final class ValkeyClusterClient: Sendable {
146146
@inlinable
147147
public func execute<Command: ValkeyCommand>(_ command: Command) async throws -> Command.Response {
148148
let hashSlot = try self.hashSlot(for: command.keysAffected)
149-
let nodeSelection =
150-
if command.isReadOnly {
151-
self.clientConfiguration.readOnlyReplicaSelection.clusterNodeSelection
152-
} else {
153-
ValkeyClusterNodeSelection.primary
154-
}
149+
let nodeSelection = getNodeSelection(readOnly: command.isReadOnly)
155150
var clientSelector: () async throws -> ValkeyNodeClient = {
156151
try await self.nodeClient(for: hashSlot.map { [$0] } ?? [], nodeSelection: nodeSelection)
157152
}
@@ -259,12 +254,7 @@ public final class ValkeyClusterClient: Sendable {
259254
) async -> [Result<RESPToken, any Error>] {
260255
guard commands.count > 0 else { return [] }
261256
let readOnlyCommand = commands.reduce(true) { $0 && $1.isReadOnly }
262-
let nodeSelection =
263-
if readOnlyCommand {
264-
self.clientConfiguration.readOnlyReplicaSelection.clusterNodeSelection
265-
} else {
266-
ValkeyClusterNodeSelection.primary
267-
}
257+
let nodeSelection = getNodeSelection(readOnly: readOnlyCommand)
268258
// get a list of nodes and the commands that should be run on them
269259
do {
270260
let nodes = try await self.splitCommandsAcrossNodes(commands: commands, nodeSelection: nodeSelection)
@@ -354,12 +344,7 @@ public final class ValkeyClusterClient: Sendable {
354344
) async throws -> [Result<RESPToken, Error>] where Commands.Element == any ValkeyCommand {
355345
let hashSlot = try self.hashSlot(for: commands.flatMap { $0.keysAffected })
356346
let readOnlyCommand = commands.reduce(true) { $0 && $1.isReadOnly }
357-
let nodeSelection =
358-
if readOnlyCommand {
359-
self.clientConfiguration.readOnlyReplicaSelection.clusterNodeSelection
360-
} else {
361-
ValkeyClusterNodeSelection.primary
362-
}
347+
let nodeSelection = getNodeSelection(readOnly: readOnlyCommand)
363348
var clientSelector: () async throws -> ValkeyNodeClient = {
364349
try await self.nodeClient(for: hashSlot.map { [$0] } ?? [], nodeSelection: nodeSelection)
365350
}
@@ -489,16 +474,20 @@ public final class ValkeyClusterClient: Sendable {
489474
operation: (ValkeyConnection) async throws -> sending Value
490475
) async throws -> Value {
491476
let hashSlots = keys.compactMap { HashSlot(key: $0) }
492-
let nodeSelection =
493-
if readOnly {
494-
self.clientConfiguration.readOnlyReplicaSelection.clusterNodeSelection
495-
} else {
496-
ValkeyClusterNodeSelection.primary
497-
}
477+
let nodeSelection = getNodeSelection(readOnly: readOnly)
498478
let node = try await self.nodeClient(for: hashSlots, nodeSelection: nodeSelection)
499479
return try await node.withConnection(isolation: isolation, operation: operation)
500480
}
501481

482+
@inlinable
483+
/* private */ func getNodeSelection(readOnly: Bool) -> ValkeyClusterNodeSelection {
484+
if readOnly {
485+
self.clientConfiguration.readOnlyCommandNodeSelection.clusterNodeSelection
486+
} else {
487+
.primary
488+
}
489+
}
490+
502491
/// Starts running the cluster client.
503492
///
504493
/// This method initiates:

Sources/Valkey/Cluster/ValkeyClusterNodeSelection.swift

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
package enum ValkeyClusterNodeSelection: Sendable {
1111
case primary
1212
case cycleReplicas(Int)
13+
case cycleAllNodes(Int)
1314

1415
/// Select node from node ids
1516
/// - Parameter nodeIDs: Primary and replica nodes
@@ -22,20 +23,29 @@ package enum ValkeyClusterNodeSelection: Sendable {
2223
case .cycleReplicas(let index):
2324
guard nodeIDs.replicas.count > 0 else { return nodeIDs.primary }
2425
return nodeIDs.replicas[index % nodeIDs.replicas.count]
26+
case .cycleAllNodes(let index):
27+
let index = index % (nodeIDs.replicas.count + 1)
28+
if index == 0 {
29+
return nodeIDs.primary
30+
} else {
31+
return nodeIDs.replicas[index - 1]
32+
}
2533
}
2634
}
2735
}
2836

2937
@available(valkeySwift 1.0, *)
30-
extension ValkeyClientConfiguration.ReadOnlyReplicaSelection {
31-
/// Convert from read only replica selection to node selection
38+
extension ValkeyClientConfiguration.ReadOnlyCommandNodeSelection {
39+
/// Convert from ``ValkeyClientConfiguration/ReadOnlyCommandNodeSelection`` to node selection
3240
@usableFromInline
3341
var clusterNodeSelection: ValkeyClusterNodeSelection {
3442
switch self.value {
35-
case .none:
43+
case .primary:
3644
.primary
37-
case .cycle:
45+
case .cycleReplicas:
3846
.cycleReplicas(Self.idGenerator.next())
47+
case .cycleAllNodes:
48+
.cycleAllNodes(Self.idGenerator.next())
3949
}
4050
}
4151

Sources/Valkey/ValkeyClientConfiguration.swift

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -153,19 +153,22 @@ public struct ValkeyClientConfiguration: Sendable {
153153
}
154154
}
155155

156-
/// Determine how replicas are chosen for readonly commands
157-
public struct ReadOnlyReplicaSelection: Sendable {
156+
/// Determine how nodes are chosen for readonly commands
157+
public struct ReadOnlyCommandNodeSelection: Sendable {
158158
enum _Internal {
159-
case none
160-
case cycle
159+
case primary
160+
case cycleReplicas
161+
case cycleAllNodes
161162
}
162163

163164
let value: _Internal
164165

165-
/// Do not use readonly replicas
166-
public static var none: Self { .init(value: .none) }
166+
/// Always use the primary node
167+
public static var primary: Self { .init(value: .primary) }
167168
/// Cycle through replicas
168-
public static var cycle: Self { .init(value: .cycle) }
169+
public static var cycleReplicas: Self { .init(value: .cycleReplicas) }
170+
/// Cycle through primary and replicas
171+
public static var cycleAllNodes: Self { .init(value: .cycleAllNodes) }
169172
}
170173

171174
/// The authentication credentials for the connection.
@@ -186,15 +189,13 @@ public struct ValkeyClientConfiguration: Sendable {
186189
/// The TLS to use for the Valkey connection.
187190
public var tls: TLS
188191

189-
/// Determine how we chose replicas for readonly commands
190-
///
191-
/// A nil value indicates we do not want to use readonly replicas
192+
/// Determine how we chose nodes for readonly commands
192193
///
193194
/// Cluster by default will redirect commands from replica nodes to the primary node.
194-
/// Setting this value will allow replicas to run readonly commands. This will reduce
195-
/// load on your primary nodes but there is a chance you will receive stale data as
196-
/// the replica is not up to date.
197-
public var readOnlyReplicaSelection: ReadOnlyReplicaSelection
195+
/// Setting this value to something other than ``ReadOnlyCommandNodeSelection/primary``
196+
/// will allow replicas to run readonly commands. This will reduce load on your primary
197+
/// nodes but there is a chance you will receive stale data as the replica is not up to date.
198+
public var readOnlyCommandNodeSelection: ReadOnlyCommandNodeSelection
198199

199200
#if DistributedTracingSupport
200201
/// The distributed tracing configuration to use for the Valkey connection.
@@ -221,7 +222,7 @@ public struct ValkeyClientConfiguration: Sendable {
221222
commandTimeout: Duration = .seconds(30),
222223
blockingCommandTimeout: Duration = .seconds(120),
223224
tls: TLS = .disable,
224-
readOnlyReplicaSelection: ReadOnlyReplicaSelection = .none
225+
readOnlyCommandNodeSelection: ReadOnlyCommandNodeSelection = .primary
225226
) {
226227
self.authentication = authentication
227228
self.connectionPool = connectionPool
@@ -230,6 +231,6 @@ public struct ValkeyClientConfiguration: Sendable {
230231
self.commandTimeout = commandTimeout
231232
self.blockingCommandTimeout = blockingCommandTimeout
232233
self.tls = tls
233-
self.readOnlyReplicaSelection = readOnlyReplicaSelection
234+
self.readOnlyCommandNodeSelection = readOnlyCommandNodeSelection
234235
}
235236
}

0 commit comments

Comments
 (0)