Giter Club home page Giter Club logo

redis's Introduction

redis's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

redis's Issues

Support for Cocoapods

Hi czechboy0,

is it possible to support cocoapods as package manager too?

That would be great.
Seppelandrio

pipelining

It would be nice to have a way to send multiple commands at once. This api feels a bit out of place now in vapor 3 but something similar would be nice.

 let pipeline = connection.makePipeline()
 let result = try pipeline
         .enqueue(command: "SET", arguments: ["KEY", "VALUE"])
         .enqueue(command: "INCR", arguments: ["COUNT"])
         .execute() // Future<[RedisData]>

Throw on connection failure

I kind of goofed up and did not spec that Redis client should throw on connection failure... I will fix it.

Timeout & automatic reconnect

  • test the client when Redis auto-disconnects after a while (we throw an error)
  • when that happens, have an option to auto-connect (and auto-authenticate?) (nope, not at the moment)
  • do we need to handle SIGPIPE (accidental writing into a closed socket)? (no, we throw an error already)

Redbird client as a stored class property

Hello,

More a question than an issue: i'm playing with your redis client and I'm wrapping it in a class to abstract db specific stuff in my app. I have a problem initializing this class though since init of Redis throws.

Here's what I'm trying to do:

class RedisManager {
  let client: Redbird
  init(address: String, port: UInt16, password: String? = nil) {
    do {
      let config = RedbirdConfig(address: address, port: port, password: password)
      client = try Redbird(config: config)
    } catch {
      Log.error("Could not connect to Redis instance")
    }
  }
...
# Api like setArray, getString ...
}

This fails with error:

Return from initializer without initializing all stored properties

I want to keep an instance of Redis as a stored property because it seems wasteful to recreate it inside a do catch every time I want to access db.

Any idea how to instantiate Redis in init of my class and assign it to self.client?

RedisDataDecoder#parseBulkString Array index is out of range

guard let bytes = buffer.peekBytes(at: position, length: byteCount) else { return .notYetParsed }
defer { position += size + 2 }
return .parsed(.bulkString(Data(bytes[..<size])))

Stumbled upon the crash today with slicing bytes array with size out of range.
The state at that moment was:

size == 10
buffer.readableBytes == 115
position == 113
bytes: 2 elements

and the buffer.readString(length: 115) output

"*8\r\n$16\r\ntest8:1523640910\r\n$10\r\n1523640910\r\n$16\r\ntest9:1523640913\r\n$10\r\n1523640913\r\n$17\r\ntest10:1523640916\r\n$10\r\n15"

Is out of range expected behaviour with that buffer?

Redis: Subscribing to multiple channels

There is an issue when subscribing to multiple Channels with Redis. PubSub with a single channel works just fine but as soon as multiple channels are attempted there is an issue. I used redis-cli and MONITOR to investigate this "SUBSCRIBE" command goes across the wire as expected however no channel data is coming out of the drain. RedisDataParser does not get channel data that it can decipher.

I can provide sample code to reproduce this if that is what is desired.

Support for pub-sub

Apologies if I missed something, but it seems like pub-sub is currently not supported? From what I see, when calling command, it does both a write and a read of the response on the socket, and there's no finer-grained method to just emit a write and a separate one for the reads, which are required for pub-sub (you call [P]SUBSCRIBE with a write, and then wait for messages by reading on the socket - it typically can't be used for other writes except to subscribe/unsubscribe to/from other channels).

For example, the redigo package in Go has separate Send/Flush calls to write, and Receive to read, and a convenience Do method that combines them for the common commands that immediately return a value (https://godoc.org/github.com/garyburd/redigo/redis#Conn). It also provides a PubSubConn type as convenience, built from the Send/Flush/Receive primitives (https://godoc.org/github.com/garyburd/redigo/redis#PubSubConn).

Cannot call commands with more than 1 word

Many redis commands are composed of multiple words, but in Redbird.swift there's a validation that the command must be a single word otherwise it's an error (RedbirdError.moreThanOneWordSpecifiedAsCommand).

e.g. if you try client.command("CONFIG GET", params: ["*"]).

IMO you shouldn't try to validate the command at all, as redis will soon support modules which may define additional commands (currently in the unstable branch), and the config allows to rename known commands to something else (see rename-command in https://raw.githubusercontent.com/antirez/redis/3.0/redis.conf). I think you should consider whatever's passed into command method to be the command to execute.

Add conveniences for common redis commands.

Commands

String

  • MSET
  • MGET
  • INCR
  • INCRBY
  • DECR
  • DECRBY
  • DEL

List

  • RPUSH
  • LPUSH
  • LRANGE
  • LINDEX
  • LLEN
  • LSET
  • RPOP
  • RPOPLPUSH

Sets

  • SADD
  • SCARD
  • SREM
  • SISMEMBER
  • SMEMBERS

Sorted Sets

  • ZADD
  • ZCARD
  • ZCOUNT
  • ZINCRBY
  • ZRANGE
  • ZRANK
  • ZREMRANGEBYRANK
  • ZREMRANGEBYSCORE
  • ZREM
  • ZSCORE

Hashes

  • HGET
  • HGETALL
  • HSET
  • HMSET
  • HINCRBY

HyperLogLog

  • PFADD
  • PFCOUNT

Redis Setup

Currently there is no way to setup Redis with a Keyed Session because that requires access to the RedisClient, which we don't have during the setup.

From the Slack:

Ideally the keyed cache would take either a Future to redis, or a connection pool

Integer Type Conversion

Currently the toInt() method only succeeds when Redis returns an explicit integer type, prefixed with :. This may be expected behavior, but I don't find it particularly useful since most types are returned as bulk string.

Would you consider expanding the toInt() method to convert bulk strings to Int as well?

Redis Command is successfully executed but still throws error

do{
    let result = try redis.command("SETNX", params: ["test", "redbird"]).toString()
}
catch{
    print(error) //This prints wrongNativeTypeUnboxing(Redbird.RespInteger(respType: Redbird.RespType.Integer, intContent: 0), "String")
}

I checked the key in my redis and the value is successfully set

127.0.0.1:6379> get test
"redbird"

There is some problem with setnx command. Please resolve this issue as it is throwing error even if there is success

Basic auth support

Is there a way to authenticate using user/password ? (For Heroku's Redis service)

RedisDataDecoder#parse invalidTypeToken

throw RedisError(
identifier: "invalidTypeToken",
reason: "Unexpected error while parsing RedisData.",
source: .capture()

buffer =
"*50\r\n$5\r\ntest0\r\n$5\r\ntest1\r\n$6\r\ntest10\r\n$6\r\ntest11\r\n$6\r\ntest12\r\n$6\r\ntest13\r\n$6\r\ntest14\r\n$6\r\ntest15\r\n$6\r\ntest16\r\n$6\r\ntest17\r\n$6\r\ntest18\r\n$6\r\ntest19\r\n$5\r\ntest2\r\n$6\r\ntest20\r\n$6\r\ntest21\r\n$6\r\ntest22\r\n$6\r\ntest23\r\n$6\r\ntest24\r\n$6\r\ntest25\r\n$6\r\ntest26\r\n$6\r\ntest27\r\n$6\r\ntest28\r\n$6\r\ntest29\r\n$5\r\ntest3\r\n$6\r\ntest30\r\n$6\r\ntest31\r\n"

position = 314
token = 54

Redis Configuration Not Public

The API to configure Redis is currently not public. This is well within my new guy abilities. So I am going to take a stab at it.

Updating from v1 to v2

Hello, so I've been planning on updating an application of mine that used the version 1 of this library to the more recent one, and I'm having some doubts about how to proceed.
It seems that not all of the available redis operations are defined now, for example, how do I convert 'MULTI', 'EXEC', 'HGETALL', etc?

Also, is there any documentation (or blog post, etc) with some examples on the recent version?
Cheers!

Do all commands work ?

I'm trying to set an hmap with this line :

let message = try client!.command("HMSET", params: ["messages", "content", "blalba", "token", "123456"])
let writtenMessages = try client.command("HGET", params: ["messages", "content"])

But printing writtenMessages.toString() gives me the "OK" message instead of the content...

I have no idea how to do this, so is this supported, if so how do you do it ?

input was called while inputBuffer is not nil

  • OS: macOS High Sierra
  • Redis version: 2d150f6

Expected Behavior

Using the run(command:arguments:) should succeed!

Current Behavior

Using the run(command:arguments:), I encountered many such errors. I cannot pin point the exact condition for this to happen since it sometimes work.

Fatal error: input was called while inputBuffer is not nil: file /Users/hsupengjun/Projects/Libraries/JARPC-upstream/.build/checkouts/async.git-2335297525913451934/Sources/Async/Socket/SocketSink.swift, line 44
Illegal instruction: 4

The code that could cause the error (there are quite some more),

_ = client.run(command: "LPUSH", arguments: [.bulkString(target), .bulkString(data)])
_ = client.run(command: "LREM", arguments: [.bulkString(processingQueue), "0", .bulkString(work)])

The resolved packages,

{
  "package": "Async",
  "repositoryURL": "https://github.com/vapor/async.git",
  "state": {
    "branch": "beta",
    "revision": "e2dec3c2013d5c71e3ebace661344de7d1259b79",
    "version": null
  }
},
{
  "package": "Redis",
  "repositoryURL": "https://github.com/vapor/redis.git",
  "state": {
    "branch": "beta",
    "revision": "2d150f6ec90b1071a0633272180c4dafc1043f92",
    "version": null
  }
},

Screenshot of call stack,

2017-12-22 10 00 50


How to Reproduce

I actually don't know how.

If my bug report is malformed or otherwise, please mention me. I can provide exact code through PM in Slack if needed. :)

Not getting the full string value

After playing around with this for a while. I figured out the reason for the error was in here.

If you store a key:value and retrieve it fast enough, in some cases you will only get some of the value string back

ex

sometimes: GET:{"dat
should be: GET:{"data":null}

I managed to replicate this, by setting up a sessionmiddleware with redis cache. And then refresh a view which is using files from public folder

maybe it's related to: #31?

Memory Leak

Running wrk -t4 -c100 -d10s http://127.0.0.1:8080/test creates 358 megabytes of memory for me.
Currently happening on 3.0.0-rc.

 struct Car: Content {
        let wheels: Int
        let color: String
        let horsepower: Int
        let brand: String
    }
    
    
    func test(_ req: Request) throws -> Future<Car> {
        let client = try req.make(RedisClient.self)
        return try client.get(Car.self, forKey: "car").unwrap(or: "ERROR")
    }

Thread Safety

Redbird is not thread-safe, which causes problems when using it with Swift web frameworks. A single Redbird instance cannot be shared across the application, since multiple threads may require simultaneous access. Establishing a new connection for every request would be wasteful and silly.

This leaves us with two options:

  1. Force the user to synchronize all calls to a shared Redbird instance. For example:
dispatch_sync(com.myApp.redbirdSerialQueue) {
    redbird.command(...)
}
  1. Account for thread safety within Redbird itself. For example, command() may be synchronized as such:
public func command(_ name: String, params: [String] = []) throws -> RespObject {
    dispatch_sync(com.redbird.serialQueue) {
        ...
    }
}

Correct me if I'm wrong (because I'm not familiar with the entire codebase), but concurrent access to a shared Redbird instance should be safe since none of its properties are mutated after initialization.

I personally believe that option 2 is much safer and easier. What do you think? I can make the changes if you agree that thread safety should be addressed.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.