mirror of
https://github.com/swift-server/RediStack.git
synced 2026-05-03 07:32:28 +00:00
Iterate on type safety for zadd
Motivation: Issue #60 called for improving the type safety of the options available for the `zadd` command, and MR !70 made some great headway, but attempted to cram too much into a single enum. Modifications: - Break the `RedisSortedSetAddOption.returnChangedCount` value into an additional boolean param Result: Using `zadd` should now be more straight forward, while being type safe.
This commit is contained in:
@@ -47,45 +47,43 @@ extension RedisClient {
|
||||
// MARK: General
|
||||
|
||||
/// The supported options for the `zadd` command with Redis SortedSet types.
|
||||
/// - Important: Per Redis documentation, `.onlyUpdateExistingElements` and `.onlyAddNewElements` are mutually exclusive!
|
||||
/// - Note: `INCR` is not supported by this library in `zadd`. Use the `zincrby(:element:in:)` method instead.
|
||||
///
|
||||
/// See [https://redis.io/commands/zadd#zadd-options-redis-302-or-greater](https://redis.io/commands/zadd#zadd-options-redis-302-or-greater)
|
||||
public enum RedisSortedSetAddOption: String {
|
||||
/// When adding elements, any that do not already exist in the SortedSet will be ignored and the score of the existing element will be updated.
|
||||
case onlyUpdateExistingElements = "XX"
|
||||
/// When adding elements, any that already exist in the SortedSet will be ignored and the score of the existing element will not be updated.
|
||||
case onlyAddNewElements = "NX"
|
||||
/// `zadd` normally returns the number of new elements added to the set,
|
||||
/// but this option will instead have the command return the number of elements changed.
|
||||
///
|
||||
/// "Changed" in this context are new elements added, and elements that had their score updated.
|
||||
case returnChangedCount = "CH"
|
||||
}
|
||||
|
||||
extension RedisClient {
|
||||
/// Adds elements to a sorted set, assigning their score to the values provided.
|
||||
/// - Note: `INCR` is not supported by this library in `zadd`. Use the `zincrby(:element:in:)` method instead.
|
||||
///
|
||||
/// See [https://redis.io/commands/zadd](https://redis.io/commands/zadd)
|
||||
/// - Parameters:
|
||||
/// - elements: A list of elements and their score to add to the sorted set.
|
||||
/// - key: The key of the sorted set.
|
||||
/// - options: A set of options defined by Redis for this command to execute under.
|
||||
/// - Returns: The number of elements added to the sorted set.
|
||||
/// - option: An option for modifying the behavior of the command.
|
||||
/// - returnChangedCount: `zadd` normally returns the number of new elements added to the set,
|
||||
/// but setting this to `true` will instead have the command return the number of elements changed.
|
||||
///
|
||||
/// "Changed" in this context are new elements added, and elements that had their score updated.
|
||||
/// - Returns: The number of elements added to the sorted set, unless `returnChangedCount` was set to `true`.
|
||||
@inlinable
|
||||
public func zadd<Value: RESPValueConvertible>(
|
||||
_ elements: [(element: Value, score: Double)],
|
||||
to key: String,
|
||||
options: Set<RedisSortedSetAddOption> = []
|
||||
option: RedisSortedSetAddOption? = nil,
|
||||
returnChangedCount: Bool = false
|
||||
) -> EventLoopFuture<Int> {
|
||||
assert(options.count <= 2, "Invalid number of options provided.")
|
||||
assert(
|
||||
!(options.contains(.onlyAddNewElements) && options.contains(.onlyUpdateExistingElements)),
|
||||
".onlyAddNewElements and .onlyUpdateExistingElements options are mutually exclusive."
|
||||
)
|
||||
|
||||
var args: [RESPValue] = [.init(bulk: key)]
|
||||
args.add(contentsOf: options) { (array, option) in
|
||||
array.append(.init(bulk: option.rawValue))
|
||||
|
||||
if let opt = option {
|
||||
args.append(.init(bulk: opt.rawValue))
|
||||
}
|
||||
if returnChangedCount {
|
||||
args.append(.init(bulk: "CH"))
|
||||
}
|
||||
args.add(contentsOf: elements, overestimatedCountBeingAdded: elements.count * 2) { (array, next) in
|
||||
array.append(.init(bulk: next.score.description))
|
||||
@@ -102,15 +100,20 @@ extension RedisClient {
|
||||
/// - Parameters:
|
||||
/// - element: The element and its score to add to the sorted set.
|
||||
/// - key: The key of the sorted set.
|
||||
/// - options: A set of options defined by Redis for this command to execute under.
|
||||
/// - Returns: `true` if the element was added or score was updated in the sorted set.
|
||||
/// - option: An option for modifying the behavior of the command.
|
||||
/// - returnChangedCount: `zadd` normally returns the number of new elements added to the set,
|
||||
/// but setting this to `true` will instead have the command return the number of elements changed.
|
||||
///
|
||||
/// "Changed" in this context are new elements added, and elements that had their score updated.
|
||||
/// - Returns: `true` if the element was added or score was updated in the sorted set, depending on the `option` and `returnChangedCount` settings set.
|
||||
@inlinable
|
||||
public func zadd<Value: RESPValueConvertible>(
|
||||
_ element: (element: Value, score: Double),
|
||||
to key: String,
|
||||
options: Set<RedisSortedSetAddOption> = []
|
||||
option: RedisSortedSetAddOption? = nil,
|
||||
returnChangedCount: Bool = false
|
||||
) -> EventLoopFuture<Bool> {
|
||||
return zadd([element], to: key, options: options)
|
||||
return zadd([element], to: key, option: option, returnChangedCount: returnChangedCount)
|
||||
.map { return $0 == 1 }
|
||||
}
|
||||
|
||||
|
||||
@@ -43,18 +43,19 @@ final class SortedSetCommandsTests: RedisIntegrationTestCase {
|
||||
XCTAssertEqual(count, 1)
|
||||
count = try connection.zadd([(30, 5)], to: #function).wait()
|
||||
XCTAssertEqual(count, 0)
|
||||
count = try connection.zadd([(30, 6), (31, 0), (32, 1)], to: #function, options: [.onlyAddNewElements]).wait()
|
||||
count = try connection.zadd([(30, 6), (31, 0), (32, 1)], to: #function, option: .onlyAddNewElements).wait()
|
||||
XCTAssertEqual(count, 2)
|
||||
count = try connection.zadd(
|
||||
[(32, 2), (33, 3)],
|
||||
to: #function,
|
||||
options: [.onlyUpdateExistingElements, .returnChangedCount]
|
||||
option: .onlyUpdateExistingElements,
|
||||
returnChangedCount: true
|
||||
).wait()
|
||||
XCTAssertEqual(count, 1)
|
||||
|
||||
var success = try connection.zadd((30, 7), to: #function, options: [.returnChangedCount]).wait()
|
||||
var success = try connection.zadd((30, 7), to: #function, returnChangedCount: true).wait()
|
||||
XCTAssertTrue(success)
|
||||
success = try connection.zadd((30, 8), to: #function, options: [.onlyAddNewElements]).wait()
|
||||
success = try connection.zadd((30, 8), to: #function, option: .onlyAddNewElements).wait()
|
||||
XCTAssertFalse(success)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user