Skip to content

Commit 5b1377b

Browse files
committed
Add convienence methods for "basic" commands
1 parent a41fe56 commit 5b1377b

File tree

3 files changed

+139
-0
lines changed

3 files changed

+139
-0
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import Foundation
2+
import NIO
3+
4+
extension NIORedisConnection {
5+
/// Select the Redis logical database having the specified zero-based numeric index.
6+
/// New connections always use the database 0.
7+
///
8+
/// https://redis.io/commands/select
9+
public func select(_ id: Int) -> EventLoopFuture<Void> {
10+
return command("SELECT", [RedisData(bulk: id.description)])
11+
.map { _ in return () }
12+
}
13+
14+
/// Removes the specified keys. A key is ignored if it does not exist.
15+
///
16+
/// https://redis.io/commands/del
17+
/// - Returns: A future number of keys that were removed.
18+
public func delete(_ keys: String...) -> EventLoopFuture<Int> {
19+
let keyArgs = keys.map { RedisData(bulk: $0) }
20+
return command("DEL", keyArgs)
21+
.thenThrowing { res in
22+
guard let count = res.int else {
23+
throw RedisError(identifier: "delete", reason: "Unexpected response: \(res)")
24+
}
25+
return count
26+
}
27+
}
28+
29+
/// Set a timeout on key. After the timeout has expired, the key will automatically be deleted.
30+
/// A key with an associated timeout is often said to be volatile in Redis terminology.
31+
///
32+
/// https://redis.io/commands/expire
33+
/// - Parameters:
34+
/// - after: The lifetime (in seconds) the key will expirate at.
35+
/// - Returns: A future bool indicating if the expiration was set or not.
36+
public func expire(_ key: String, after deadline: Int) -> EventLoopFuture<Bool> {
37+
return command("EXPIRE", [RedisData(bulk: key), RedisData(bulk: deadline.description)])
38+
.thenThrowing { res in
39+
guard let value = res.int else {
40+
throw RedisError(identifier: "expire", reason: "Unexpected response: \(res)")
41+
}
42+
return value == 1
43+
}
44+
}
45+
46+
/// Get the value of a key.
47+
/// If the key does not exist the value will be `nil`.
48+
/// An error is resolved if the value stored at key is not a string, because GET only handles string values.
49+
///
50+
/// https://redis.io/commands/get
51+
public func get(_ key: String) -> EventLoopFuture<String?> {
52+
return command("GET", [RedisData(bulk: key)])
53+
.map { return $0.string }
54+
}
55+
56+
/// Set key to hold the string value.
57+
/// If key already holds a value, it is overwritten, regardless of its type.
58+
/// Any previous time to live associated with the key is discarded on successful SET operation.
59+
///
60+
/// https://redis.io/commands/set
61+
public func set(_ key: String, to value: String) -> EventLoopFuture<Void> {
62+
return command("SET", [RedisData(bulk: key), RedisData(bulk: value)])
63+
.map { _ in return () }
64+
}
65+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
@testable import NIORedis
2+
import XCTest
3+
4+
final class BasicCommandsTests: XCTestCase {
5+
private let redis = NIORedis(executionModel: .spawnThreads(1))
6+
deinit { try? redis.terminate() }
7+
8+
private var connection: NIORedisConnection?
9+
10+
override func setUp() {
11+
do {
12+
connection = try redis.makeConnection().wait()
13+
} catch {
14+
XCTFail("Failed to create NIORedisConnection!")
15+
}
16+
}
17+
18+
override func tearDown() {
19+
_ = try? connection?.command("FLUSHALL").wait()
20+
connection?.close()
21+
connection = nil
22+
}
23+
24+
func test_select() {
25+
XCTAssertNoThrow(try connection?.select(3).wait())
26+
}
27+
28+
func test_delete() throws {
29+
let keys = [ #function + "1", #function + "2", #function + "3" ]
30+
try connection?.set(keys[0], to: "value").wait()
31+
try connection?.set(keys[1], to: "value").wait()
32+
try connection?.set(keys[2], to: "value").wait()
33+
34+
let first = try connection?.delete(keys[0]).wait()
35+
XCTAssertEqual(first, 1)
36+
37+
let second = try connection?.delete(keys[0]).wait()
38+
XCTAssertEqual(second, 0)
39+
40+
let third = try connection?.delete(keys[1], keys[2]).wait()
41+
XCTAssertEqual(third, 2)
42+
}
43+
44+
func test_set() {
45+
XCTAssertNoThrow(try connection?.set(#function, to: "value").wait())
46+
}
47+
48+
func test_get() throws {
49+
try connection?.set(#function, to: "value").wait()
50+
let result = try connection?.get(#function).wait()
51+
XCTAssertEqual(result, "value")
52+
}
53+
54+
func test_expire() throws {
55+
try connection?.set(#function, to: "value").wait()
56+
let before = try connection?.get(#function).wait()
57+
XCTAssertNotNil(before)
58+
59+
let result = try connection?.expire(#function, after: 0).wait()
60+
XCTAssertEqual(result, true)
61+
62+
let after = try connection?.get(#function).wait()
63+
XCTAssertNil(after)
64+
}
65+
66+
static var allTests = [
67+
("test_select", test_select),
68+
("test_set", test_set),
69+
("test_get", test_get),
70+
("test_expire", test_expire),
71+
("test_delete", test_delete),
72+
]
73+
}

Tests/NIORedisTests/XCTestManifests.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public func allTests() -> [XCTestCaseEntry] {
99
testCase(RedisDataDecoderByteToMessageDecoderTests.allTests),
1010
testCase(RedisDataEncoderTests.allTests),
1111
testCase(RedisDataEncoderParsingTests.allTests),
12+
testCase(BasicCommandsTests.allTests),
1213
]
1314
}
1415
#endif

0 commit comments

Comments
 (0)