Skip to content

Commit

Permalink
92 -- Accept event loop and logger in RedisClient commands
Browse files Browse the repository at this point in the history
There are many times that developers want exact control over which EventLoop will be executing their chained EventLoopFuture callbacks
and which Logger will do the logging in calls deep within RediStack.

All commands will now accept an optional EventLoop and Logger to hop to, and using the logger for desired logs.
  • Loading branch information
Mordil committed Apr 4, 2022
1 parent a4aec72 commit 9da5773
Show file tree
Hide file tree
Showing 20 changed files with 666 additions and 394 deletions.
40 changes: 31 additions & 9 deletions Sources/RediStack/Commands/ConnectionCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Connection
Expand Down Expand Up @@ -61,28 +62,49 @@ extension RedisClient {
/// Pings the server, which will respond with a message.
///
/// See ``RedisCommand/ping(with:)``
/// - Parameter message: The optional message that the server should respond with instead of the default.
/// - Parameters:
/// - message: The optional message that the server should respond with instead of the default.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves the given `message` or Redis' default response of `PONG`.
public func ping(with message: String? = nil) -> EventLoopFuture<String> {
return self.send(.ping(with: message))
public func ping(
with message: String? = nil,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<String> {
return self.send(.ping(with: message), eventLoop: eventLoop, logger: logger)
}

/// Requests the client to authenticate with Redis to allow other commands to be executed.
///
/// See ``RedisCommand/auth(with:)``
/// - Parameter password: The password to authenticate with.
/// - Parameters:
/// - password: The password to authenticate with.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves if the password as accepted, otherwise it fails.
public func authorize(with password: String) -> EventLoopFuture<Void> {
return self.send(.auth(with: password))
public func authorize(
with password: String,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Void> {
return self.send(.auth(with: password), eventLoop: eventLoop, logger: logger)
}

/// Selects the Redis logical database having the given zero-based numeric index.
///
/// See ``RedisCommand/select(database:)``
/// - Note: New connections always use the database `0`.
/// - Parameter index: The 0-based index of the database that the connection sending this command will execute later commands against.
/// - Parameters:
/// - index: The 0-based index of the database that the connection sending this command will execute later commands against.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` resolving once the operation has succeeded.
public func select(database index: Int) -> EventLoopFuture<Void> {
return self.send(.select(database: index))
public func select(
database index: Int,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Void> {
return self.send(.select(database: index), eventLoop: eventLoop, logger: logger)
}
}
10 changes: 7 additions & 3 deletions Sources/RediStack/Commands/HashCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Hashes
Expand Down Expand Up @@ -237,16 +238,19 @@ extension RedisClient {
/// - position: The position to start the scan from.
/// - match: A glob-style pattern to filter values to be selected from the result set.
/// - count: The number of elements to advance by. Redis default is 10.
/// - valueType: The type to cast all values to.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves a cursor position for additional scans,
/// with a limited collection of fields and their associated values that were iterated over.
public func scanHashFields(
in key: RedisKey,
startingFrom position: Int = 0,
matching match: String? = nil,
count: Int? = nil
count: Int? = nil,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<(Int, [RedisHashFieldKey: RESPValue])> {
return self.send(.hscan(key, startingFrom: position, matching: match, count: count))
return self.send(.hscan(key, startingFrom: position, matching: match, count: count), eventLoop: eventLoop, logger: logger)
}
}

Expand Down
59 changes: 46 additions & 13 deletions Sources/RediStack/Commands/KeyCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Key
Expand Down Expand Up @@ -94,20 +95,34 @@ extension RedisClient {
/// Deletes the given keys. Any key that does not exist is ignored.
///
/// See ``RedisCommand/.del(keys:)``
/// - Parameter keys: The list of keys to delete from the database.
/// - Parameters:
/// - keys: The list of keys to delete from the database.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves the number of keys that were deleted from the database.
public func delete(_ keys: RedisKey...) -> EventLoopFuture<Int> {
return self.delete(keys)
public func delete(
_ keys: RedisKey...,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Int> {
return self.delete(keys, eventLoop: eventLoop, logger: logger)
}

/// Deletes the given keys. Any key that does not exist is ignored.
///
/// See ``RedisCommand/del(keys:)``
/// - Parameter keys: The list of keys to delete from the database.
/// - Parameters:
/// - keys: The list of keys to delete from the database.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves the number of keys that were deleted from the database.
public func delete(_ keys: [RedisKey]) -> EventLoopFuture<Int> {
public func delete(
_ keys: [RedisKey],
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Int> {
guard keys.count > 0 else { return self.eventLoop.makeSucceededFuture(0) }
return self.send(.del(keys))
return self.send(.del(keys), eventLoop: eventLoop, logger: logger)
}

/// Sets a timeout on key. After the timeout has expired, the key will automatically be deleted.
Expand All @@ -116,18 +131,32 @@ extension RedisClient {
/// - Parameters:
/// - key: The key to set the expiration on.
/// - timeout: The time from now the key will expire at.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves `true` if the expiration was set and `false` if it wasn't.
public func expire(_ key: RedisKey, after timeout: TimeAmount) -> EventLoopFuture<Bool> {
return self.send(.expire(key, after: timeout))
public func expire(
_ key: RedisKey,
after timeout: TimeAmount,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Bool> {
return self.send(.expire(key, after: timeout), eventLoop: eventLoop, logger: logger)
}

/// Searches the keys in the database that match the given pattern.
///
/// See ``RedisCommand/keys(matching:)``
/// - Parameter pattern: The key pattern to search for matching keys that exist in Redis.
/// - Parameters:
/// - pattern: The key pattern to search for matching keys that exist in Redis.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A result set of ``RedisKey`` values that exist and match the provided pattern.
public func listKeys(matching pattern: String) -> EventLoopFuture<[RedisKey]> {
return self.send(.keys(matching: pattern))
public func listKeys(
matching pattern: String,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<[RedisKey]> {
return self.send(.keys(matching: pattern), eventLoop: eventLoop, logger: logger)
}

/// Incrementally iterates over all keys in the currently selected database.
Expand All @@ -137,12 +166,16 @@ extension RedisClient {
/// - position: The cursor position to start from.
/// - match: A glob-style pattern to filter values to be selected from the result set.
/// - count: The number of elements to advance by. Redis default is 10.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A cursor position for additional invocations with a limited collection of keys found in the database.
public func scanKeys(
startingFrom position: Int = 0,
matching match: String? = nil,
count: Int? = nil
count: Int? = nil,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<(Int, [RedisKey])> {
return self.send(.scan(startingFrom: position, matching: match, count: count))
return self.send(.scan(startingFrom: position, matching: match, count: count), eventLoop: eventLoop, logger: logger)
}
}
9 changes: 7 additions & 2 deletions Sources/RediStack/Commands/PubSubCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: PubSub
Expand Down Expand Up @@ -86,13 +87,17 @@ extension RedisClient {
/// - Parameters:
/// - message: The "message" value to publish on the channel.
/// - channel: The name of the channel to publish the message to.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: The number of subscribed clients that received the message.
@inlinable
@discardableResult
public func publish<Message: RESPValueConvertible>(
_ message: Message,
to channel: RedisChannelName
to channel: RedisChannelName,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Int> {
return self.send(.publish(message, to: channel))
return self.send(.publish(message, to: channel), eventLoop: eventLoop, logger: logger)
}
}
12 changes: 10 additions & 2 deletions Sources/RediStack/Commands/ServerCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Server
Expand Down Expand Up @@ -41,8 +42,15 @@ extension RedisClient {
/// - Parameters:
/// - first: The index of the first database.
/// - second: The index of the second database.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves `true` if the command succeed or `false` if it didn't.
public func swapDatabase(_ first: Int, with second: Int) -> EventLoopFuture<Bool> {
return self.send(.swapdb(first, with: second))
public func swapDatabase(
_ first: Int,
with second: Int,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<Bool> {
return self.send(.swapdb(first, with: second), eventLoop: eventLoop, logger: logger)
}
}
9 changes: 7 additions & 2 deletions Sources/RediStack/Commands/SetCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Sets
Expand Down Expand Up @@ -254,13 +255,17 @@ extension RedisClient {
/// - position: The position to start the scan from.
/// - count: The number of elements to advance by. Redis default is 10.
/// - match: A glob-style pattern to filter values to be selected from the result set.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves a cursor position for additional scans, with a limited collection of values that were iterated over.
public func scanSetValues(
in key: RedisKey,
startingFrom position: Int = 0,
matching match: String? = nil,
count: Int? = nil
count: Int? = nil,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<(Int, [RESPValue])> {
return self.send(.sscan(key, startingFrom: position, matching: match, count: count))
return self.send(.sscan(key, startingFrom: position, matching: match, count: count), eventLoop: eventLoop, logger: logger)
}
}
9 changes: 7 additions & 2 deletions Sources/RediStack/Commands/SortedSetCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
//
//===----------------------------------------------------------------------===//

import struct Logging.Logger
import NIO

// MARK: Sorted Sets
Expand Down Expand Up @@ -1154,15 +1155,19 @@ extension RedisClient {
/// - position: The position to start the scan from.
/// - match: A glob-style pattern to filter values to be selected from the result set.
/// - count: The number of elements to advance by. Redis default is 10.
/// - eventLoop: An optional event loop to hop to for any further chaining on the returned event loop future.
/// - logger: An optional logger instance to use for logs generated from this command.
/// - Returns: A `NIO.EventLoopFuture` that resolves a cursor position for additional scans,
/// with a limited collection of elements with their scores found in the Sorted Set.
public func scanSortedSetValues(
in key: RedisKey,
startingFrom position: Int = 0,
matching match: String? = nil,
count: Int? = nil
count: Int? = nil,
eventLoop: EventLoop? = nil,
logger: Logger? = nil
) -> EventLoopFuture<(Int, [(RESPValue, Double)])> {
return self.send(.zscan(key, startingFrom: position, matching: match, count: count))
return self.send(.zscan(key, startingFrom: position, matching: match, count: count), eventLoop: eventLoop, logger: logger)
}
}

Expand Down
Loading

0 comments on commit 9da5773

Please sign in to comment.