From 0ecb3c1ef321d8b66f7d731cbf8737ad5bfaf9f6 Mon Sep 17 00:00:00 2001 From: Nathan Harris Date: Tue, 9 Jul 2019 00:26:52 -0700 Subject: [PATCH] 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. --- .../Commands/SortedSetCommands.swift | 47 ++++++++++--------- .../Commands/SortedSetCommandsTests.swift | 9 ++-- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Sources/RediStack/Commands/SortedSetCommands.swift b/Sources/RediStack/Commands/SortedSetCommands.swift index d646f1a..46bf935 100644 --- a/Sources/RediStack/Commands/SortedSetCommands.swift +++ b/Sources/RediStack/Commands/SortedSetCommands.swift @@ -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( _ elements: [(element: Value, score: Double)], to key: String, - options: Set = [] + option: RedisSortedSetAddOption? = nil, + returnChangedCount: Bool = false ) -> EventLoopFuture { - 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( _ element: (element: Value, score: Double), to key: String, - options: Set = [] + option: RedisSortedSetAddOption? = nil, + returnChangedCount: Bool = false ) -> EventLoopFuture { - return zadd([element], to: key, options: options) + return zadd([element], to: key, option: option, returnChangedCount: returnChangedCount) .map { return $0 == 1 } } diff --git a/Tests/RediStackTests/Commands/SortedSetCommandsTests.swift b/Tests/RediStackTests/Commands/SortedSetCommandsTests.swift index 928e3cd..679e185 100644 --- a/Tests/RediStackTests/Commands/SortedSetCommandsTests.swift +++ b/Tests/RediStackTests/Commands/SortedSetCommandsTests.swift @@ -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) }