mirror of
https://github.com/swift-server/RediStack.git
synced 2026-06-02 07:37:33 +00:00
Merge pull request #8 from Mordil/proposal-update
Update code to match current proposal
This commit is contained in:
@@ -32,7 +32,7 @@ public final class RedisPipeline {
|
||||
/// - arguments: The arguments, if any, to send with the command.
|
||||
/// - Returns: A self-reference to this `RedisPipeline` instance for chaining commands.
|
||||
@discardableResult
|
||||
public func enqueue(command: String, arguments: [RESPConvertible] = []) throws -> RedisPipeline {
|
||||
public func enqueue(command: String, arguments: [RESPValueConvertible] = []) throws -> RedisPipeline {
|
||||
try _driverPipeline.enqueue(command: command, arguments: arguments)
|
||||
return self
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ public struct RedisCommandContext {
|
||||
/// A full command keyword and arguments stored as a single `RESPValue`.
|
||||
public let command: RESPValue
|
||||
/// A promise expected to be fulfilled with the `RESPValue` response to the command from Redis.
|
||||
public let promise: EventLoopPromise<RESPValue>
|
||||
public let responsePromise: EventLoopPromise<RESPValue>
|
||||
|
||||
public init(command: RESPValue, promise: EventLoopPromise<RESPValue>) {
|
||||
self.command = command
|
||||
self.promise = promise
|
||||
self.responsePromise = promise
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ extension RedisCommandHandler: ChannelOutboundHandler {
|
||||
/// See `ChannelOutboundHandler.write(ctx:data:promise:)`
|
||||
public func write(ctx: ChannelHandlerContext, data: NIOAny, promise: EventLoopPromise<Void>?) {
|
||||
let context = unwrapOutboundIn(data)
|
||||
commandResponseQueue.insert(context.promise, at: 0)
|
||||
commandResponseQueue.insert(context.responsePromise, at: 0)
|
||||
ctx.write(wrapOutboundOut(context.command), promise: promise)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,143 +1,111 @@
|
||||
import Foundation
|
||||
|
||||
/// Capable of converting to / from `RESPValue`.
|
||||
public protocol RESPConvertible {
|
||||
/// Create an instance of `Self` from `RESPValue`.
|
||||
static func convertFromRESP(_ value: RESPValue) throws -> Self
|
||||
public protocol RESPValueConvertible {
|
||||
init?(_ value: RESPValue)
|
||||
|
||||
/// Convert self to `RESPValue`.
|
||||
func convertToRESP() throws -> RESPValue
|
||||
/// Creates a `RESPValue` representation.
|
||||
func convertedToRESPValue() -> RESPValue
|
||||
}
|
||||
|
||||
extension RESPValue: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
extension RESPValue: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
self = value
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return self
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> RESPValue {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
extension String: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> String {
|
||||
guard let string = value.string else {
|
||||
throw RedisError(identifier: "string", reason: "Could not convert to string: \(value).")
|
||||
}
|
||||
return string
|
||||
extension String: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
guard let string = value.string else { return nil }
|
||||
self = string
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return .bulkString(Data(self.utf8))
|
||||
}
|
||||
}
|
||||
|
||||
extension FixedWidthInteger {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> Self {
|
||||
guard let int = value.int else {
|
||||
guard let string = value.string else {
|
||||
throw RedisError(identifier: "string", reason: "Could not convert to string: \(value)")
|
||||
}
|
||||
|
||||
guard let int = Self(string) else {
|
||||
throw RedisError(identifier: "int", reason: "Could not convert to int: \(value)")
|
||||
}
|
||||
|
||||
return int
|
||||
public init?(_ value: RESPValue) {
|
||||
if let int = value.int {
|
||||
self = Self(int)
|
||||
} else {
|
||||
guard let string = value.string else { return nil }
|
||||
guard let int = Self(string) else { return nil }
|
||||
self = Self(int)
|
||||
}
|
||||
|
||||
return Self(int)
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
/// See `convertedToRESP`.
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return .bulkString(Data(self.description.utf8))
|
||||
}
|
||||
}
|
||||
|
||||
extension Int: RESPConvertible {}
|
||||
extension Int8: RESPConvertible {}
|
||||
extension Int16: RESPConvertible {}
|
||||
extension Int32: RESPConvertible {}
|
||||
extension Int64: RESPConvertible {}
|
||||
extension UInt: RESPConvertible {}
|
||||
extension UInt8: RESPConvertible {}
|
||||
extension UInt16: RESPConvertible {}
|
||||
extension UInt32: RESPConvertible {}
|
||||
extension UInt64: RESPConvertible {}
|
||||
extension Int: RESPValueConvertible {}
|
||||
extension Int8: RESPValueConvertible {}
|
||||
extension Int16: RESPValueConvertible {}
|
||||
extension Int32: RESPValueConvertible {}
|
||||
extension Int64: RESPValueConvertible {}
|
||||
extension UInt: RESPValueConvertible {}
|
||||
extension UInt8: RESPValueConvertible {}
|
||||
extension UInt16: RESPValueConvertible {}
|
||||
extension UInt32: RESPValueConvertible {}
|
||||
extension UInt64: RESPValueConvertible {}
|
||||
|
||||
extension Double: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> Double {
|
||||
guard let string = value.string else {
|
||||
throw RedisError(identifier: "string", reason: "Could not convert to string: \(value).")
|
||||
}
|
||||
|
||||
guard let float = Double(string) else {
|
||||
throw RedisError(identifier: "double", reason: "Could not convert to double: \(value).")
|
||||
}
|
||||
|
||||
return float
|
||||
extension Double: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
guard let string = value.string else { return nil }
|
||||
guard let float = Double(string) else { return nil }
|
||||
self = float
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return .bulkString(Data(self.description.utf8))
|
||||
}
|
||||
}
|
||||
|
||||
extension Float: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> Float {
|
||||
guard let string = value.string else {
|
||||
throw RedisError(identifier: "string", reason: "Could not convert to string: \(value).")
|
||||
}
|
||||
|
||||
guard let float = Float(string) else {
|
||||
throw RedisError(identifier: "float", reason: "Could not convert to float: \(value).")
|
||||
}
|
||||
|
||||
return float
|
||||
extension Float: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
guard let string = value.string else { return nil }
|
||||
guard let float = Float(string) else { return nil }
|
||||
self = float
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return .bulkString(Data(self.description.utf8))
|
||||
}
|
||||
}
|
||||
|
||||
extension Data: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> Data {
|
||||
guard let theData = value.data else {
|
||||
throw RedisError(identifier: "data", reason: "Could not convert to data: \(value).")
|
||||
}
|
||||
return theData
|
||||
extension Data: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
guard let data = value.data else { return nil }
|
||||
self = data
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
return .bulkString(self)
|
||||
}
|
||||
}
|
||||
|
||||
extension Array: RESPConvertible where Element: RESPConvertible {
|
||||
/// See `RESPValueConvertible`.
|
||||
public static func convertFromRESP(_ value: RESPValue) throws -> Array<Element> {
|
||||
guard let array = value.array else {
|
||||
throw RedisError(identifier: "array", reason: "Could not convert to array: \(value).")
|
||||
}
|
||||
return try array.map { try Element.convertFromRESP($0) }
|
||||
extension Array: RESPValueConvertible where Element: RESPValueConvertible {
|
||||
public init?(_ value: RESPValue) {
|
||||
guard let array = value.array else { return nil }
|
||||
self = array.compactMap { Element($0) }
|
||||
}
|
||||
|
||||
/// See `RESPValueConvertible`.
|
||||
public func convertToRESP() throws -> RESPValue {
|
||||
let dataArray = try map { try $0.convertToRESP() }
|
||||
return RESPValue.array(dataArray)
|
||||
public func convertedToRESPValue() -> RESPValue {
|
||||
let elements = map { $0.convertedToRESPValue() }
|
||||
return RESPValue.array(elements)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +42,8 @@ public final class RedisConnection {
|
||||
/// - command: The command to execute.
|
||||
/// - arguments: The arguments to be sent with the command.
|
||||
/// - Returns: An `EventLoopFuture` that will resolve with the Redis command response.
|
||||
public func send(command: String, with arguments: [RESPConvertible] = []) throws -> EventLoopFuture<RESPValue> {
|
||||
let args = try arguments.map { try $0.convertToRESP() }
|
||||
public func send(command: String, with arguments: [RESPValueConvertible] = []) throws -> EventLoopFuture<RESPValue> {
|
||||
let args = arguments.map { $0.convertedToRESPValue() }
|
||||
return self.command(command, arguments: args)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ public final class RedisPipeline {
|
||||
/// - arguments: The arguments, if any, to send with the command.
|
||||
/// - Returns: A self-reference for chaining commands.
|
||||
@discardableResult
|
||||
public func enqueue(command: String, arguments: [RESPConvertible] = []) throws -> RedisPipeline {
|
||||
let args = try arguments.map { try $0.convertToRESP() }
|
||||
public func enqueue(command: String, arguments: [RESPValueConvertible] = []) throws -> RedisPipeline {
|
||||
let args = arguments.map { $0.convertedToRESPValue() }
|
||||
|
||||
let promise = channel.eventLoop.makePromise(of: RESPValue.self)
|
||||
let context = RedisCommandContext(
|
||||
|
||||
@@ -29,7 +29,7 @@ final class RedisDriverTests: XCTestCase {
|
||||
func test_command_succeeds() throws {
|
||||
let result = try connection.command(
|
||||
"SADD",
|
||||
arguments: [.bulkString("key".convertedToData()), try 3.convertToRESP()
|
||||
arguments: [.bulkString("key".convertedToData()), 3.convertedToRESPValue()
|
||||
]).wait()
|
||||
|
||||
XCTAssertNotNil(result.int)
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ version: 2
|
||||
jobs:
|
||||
linux:
|
||||
docker:
|
||||
- image: codevapor/swift:5.0
|
||||
- image: vapor/swift:5.0
|
||||
- image: redis:5
|
||||
steps:
|
||||
- checkout
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
- run: swift test
|
||||
linux-release:
|
||||
docker:
|
||||
- image: codevapor/swift:5.0
|
||||
- image: vapor/swift:5.0
|
||||
steps:
|
||||
- checkout
|
||||
- run: swift build -c release
|
||||
|
||||
Reference in New Issue
Block a user