Giter Site home page Giter Site logo

tiny-redis's People

Contributors

0-v-0 avatar adilbaig avatar bitdeli-chef avatar dr-mccoy avatar feepingcreature avatar geod24 avatar john-colvin avatar rnakano avatar yazd avatar

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

tiny-redis's Issues

Dub package

Is tiny-redis available as a dub package?

Stuck in infinite loop while using BLPOP command

Hi,
The BLPOP command has an optional timeout parameter. When the command times out, Redis will respond with a null array ("*-1\r\n").

This causes the receiveResponses method in the RedisConnection class to get stuck in an infinite loop. For one or some reason after parsing the count is set to 4294967295 on my system. Not 0 or -1.

I provisionally patched the response parser to look for this particular "*-1" pattern but I am not a Redis protocol specialist and cannot oversee the consequence yet.

Best regards,
Jeroen

PS Awesome library! I use it quite a lot because it is simple and very fast!

Test cases fail on older gdc versions (4.9.0, dmdfe 2.065)

14:10 $ dub test --compiler=gdc
Generating test runner configuration '__test__default__' for 'default' (library).
Building tinyredis 2.1.0 configuration "__test__default__", build type unittest.
Running gdc...
source/tinyredis/collections/set.d:100: error: module primitives is in file 'std/range/primitives.d' which cannot be read
import path[0] = /mnt/lotsostuff/dev/tools/x86_64-gdcproject-linux-gnu/include/d/4.9.0/x86_64-unknown-linux-gnu
import path[1] = /mnt/lotsostuff/dev/tools/x86_64-gdcproject-linux-gnu/include/d/4.9.0
import path[2] = /mnt/lotsostuff/dev/repos/Tiny-Redis.git/source
FAIL .dub/build/__test__default__-unittest-linux.posix-x86_64-gdc_2065-C3639316B5C48C03D979CFC6A9132E22/ __test__default__ executable
Error executing command test: gdc failed with exit code 1.

It appears we don't have std.range.primitives in that earlier version, though it's hard to tell from the Dlang docs when std.range.primitives was introduced. Because TinyRedis core doesn't rely on std.range.primitives, it would make sense to refactor the one test case using this, line 100-101 of set.d.

Possible bug in pipeline function (in redis.d)

Sometimes Redis returns the reponses from a pipeline of commands in more than one response. It appears that receiveReponses in connection.d assumes that they are all recieved in one go. I am running Ubuntu 12.10, dmd 2.061. Below is part of your example.d (which failed for me by the way) called short_ex.d. At the bottom of the file are commented sample sessions. The first run is ok. The second run, shows the results of a pipelined command being split. The tail of the response is treated as the response to a subsequent pipelined transaction. The same scenarios are also shown with -debug.

import tinyredis.redis,
std.stdio
;

/**

  • Make sure the redis server is running
    */
    void main()
    {

    auto redis = new Redis();
    scope( exit ) {
    destroy(redis);
    }

    /*
    Here's how you can add multiple items to a Redis Set
    */
    redis.send("SADD", "myset", "adil");
    redis.send("SADD", "myset", 350001939);
    redis.send("SADD", "myset", 1.2);
    redis.send("SADD", "myset", true);
    Response response = redis.send("SMEMBERS myset");
    writeln(response);

    /*
    Or you can pipeline the queries
    */
    Response[] buddies =
    redis.pipeline(["SADD buddies Batman", "SADD buddies Spiderman",
    "SADD buddies Hulk", "SMEMBERS buddies"]);
    writeln(buddies);

    /*
    Redis Transactions .. are pipelined!
    */
    Response[] responses =
    redis.transaction(["DEL ctr", "SET ctr 0", "INCR ctr", "INCR ctr"], true);
    writeln(responses);

}

/*
redis$> dmd src/short_ex.d tinyredis/*

// THIS IS OK
redis$> ./short_ex
[1.2, 1, true, adil, 350001939, $4]
[0, 0, 0, [Batman, Spiderman, Hulk]]
[OK, QUEUED, QUEUED, QUEUED, QUEUED, [1, OK, 1, 2]]

// THIS IS BAD
redis$> ./short_ex
[1.2, 1, true, adil, 350001939, $4]
[0, 0, 0]
[[Batman, Spiderman, Hulk]]

*/

/* debug

redis$> ./short_ex
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$4\r\nadil\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$9\r\n350001939\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$3\r\n1.2\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$4\r\ntrue\r\n'
Response : ':0\r\n' Length : 4
Request : '_2\r\n$8\r\nSMEMBERS\r\n$5\r\nmyset\r\n'
Response : '_6\r\n$3\r\n1.2\r\n$1\r\n1\r\n$4\r\ntrue\r\n$4\r\nadil\r\n$9\r\n350001939\r\n$2\r\n$4\r\n' Length : 63
[1.2, 1, true, adil, 350001939, $4]

// Request : '_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$6\r\nBatman\r\n_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$9\r\nSpiderman\r\n_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$4\r\nHulk\r\n_2\r\n$8\r\nSMEMBERS\r\n$7\r\nbuddies\r\n'

// Response : ':0\r\n:0\r\n:0\r\n*3\r\n$6\r\nBatman\r\n$9\r\nSpiderman\r\n$4\r\nHulk\r\n' Length : 53
// [0, 0, 0, [Batman, Spiderman, Hulk]]

Request : '_1\r\n$5\r\nMULTI\r\n_2\r\n$3\r\nDEL\r\n$3\r\nctr\r\n_3\r\n$3\r\nSET\r\n$3\r\nctr\r\n$1\r\n0\r\n_2\r\n$4\r\nINCR\r\n$3\r\nctr\r\n_2\r\n$4\r\nINCR\r\n$3\r\nctr\r\n_1\r\n$4\r\nEXEC\r\n'
Response : '+OK\r\n+QUEUED\r\n+QUEUED\r\n+QUEUED\r\n+QUEUED\r\n*4\r\n:1\r\n+OK\r\n:1\r\n:2\r\n' Length : 62
[OK, QUEUED, QUEUED, QUEUED, QUEUED, [1, OK, 1, 2]]
r

redis$> ./short_ex
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$4\r\nadil\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$9\r\n350001939\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$3\r\n1.2\r\n'
Response : ':0\r\n' Length : 4
Request : '_3\r\n$4\r\nSADD\r\n$5\r\nmyset\r\n$4\r\ntrue\r\n'
Response : ':0\r\n' Length : 4
Request : '_2\r\n$8\r\nSMEMBERS\r\n$5\r\nmyset\r\n'
Response : '_6\r\n$3\r\n1.2\r\n$1\r\n1\r\n$4\r\ntrue\r\n$4\r\nadil\r\n$9\r\n350001939\r\n$2\r\n$4\r\n' Length : 63
[1.2, 1, true, adil, 350001939, $4]

// Request : '_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$6\r\nBatman\r\n_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$9\r\nSpiderman\r\n_3\r\n$4\r\nSADD\r\n$7\r\nbuddies\r\n$4\r\nHulk\r\n_2\r\n$8\r\nSMEMBERS\r\n$7\r\nbuddies\r\n'

// Response : ':0\r\n:0\r\n:0\r\n' Length : 12
// [0, 0, 0]

Request : '_1\r\n$5\r\nMULTI\r\n_2\r\n$3\r\nDEL\r\n$3\r\nctr\r\n_3\r\n$3\r\nSET\r\n$3\r\nctr\r\n$1\r\n0\r\n_2\r\n$4\r\nINCR\r\n$3\r\nctr\r\n_2\r\n$4\r\nINCR\r\n$3\r\nctr\r\n_1\r\n$4\r\nEXEC\r\n'
// Response : '*3\r\n$6\r\nBatman\r\n$9\r\nSpiderman\r\n$4\r\nHulk\r\n' Length : 41
// [[Batman, Spiderman, Hulk]]

*/

binary strings

Hi.

One of the nice things about redis is that strings can be binary. This facilitates use with binary object serialisation using msgpack, for example.

I think you do not implement opCast for ubyte[], which is what would be needed for this purpose.

Am I missing something, or is it worth considering this enhancement?

Laeeth.

Error on template instance

After a dmd update:

$ dub build
/usr/include/dlang/dmd/std/format.d(6304,26): Error: type char is not an expression
source/tinyredis/encoder.d(169,15): Error: template instance `tinyredis.encoder.toBulk!char` error instantiating
source/tinyredis/encoder.d(51,31):        instantiated from here: accumulator!(char, string)
source/tinyredis/redis.d(64,31):        instantiated from here: toMultiBulk!(char, string)
source/tinyredis/collections/set.d(30,22):        instantiated from here: send!(Response, string)
source/tinyredis/collections/set.d(35,31): Error: template instance `tinyredis.redis.Redis.send!(int, string)` error instantiating
source/tinyredis/encoder.d(51,31): Error: template instance `tinyredis.encoder.accumulator!(char, string, const(char)[])` error instantiating
source/tinyredis/redis.d(64,31):        instantiated from here: toMultiBulk!(char, string, const(char)[])
source/tinyredis/collections/set.d(42,32):        instantiated from here: send!(bool, string, const(char)[])
source/tinyredis/collections/set.d(53,12): Error: template instance `tinyredis.redis.Redis.send!(Response, string, const(char)[])` error instantiating
/usr/include/dlang/dmd/std/format.d(6304,26): Error: type char is not an expression
source/tinyredis/redis.d(106,30): Error: template instance `tinyredis.encoder.toMultiBulk!char` error instantiating
source/tinyredis/redis.d(129,32):        instantiated from here: pipeline!(immutable(char))

My environment:

$ dmd --version
DMD64 D Compiler v2.087.0

$ dub --version
DUB version 1.16.0, built on Jul 02 2019

$ uname --all
Linux abe 5.1.9-arch1-1-ARCH #1 SMP PREEMPT Tue Jun 11 16:18:09 UTC 2019 x86_64 GNU/Linux

With ldc compiler works.

Thank you

Using TinyRedis? Add your name here

This is a notice to all users of TinyRedis. If you are using this library for your app, website or startup i'd love to hear your feedback. Even a simple mention of your name and your website is nice. Thx!

Typos in web page example html (not in repo itself)

See modified version below, which seems to work.

import tinyredis.redis;
import std.stdio;

void main()
{

auto redis = new Redis("localhost", 6379);
redis.send("SET name Adil");
writeln("The name's ", redis.send("GET name")); //The name's Adil

//Add data to a set and read it
redis.send("SADD", "fruits", ["apples", "oranges", "bananas"]);
auto fruits = redis.send("SMEMBERS", "fruits");
foreach(k, fruit; fruits)
    writeln(k, ") ", fruit);

//Cast your results
//writefln("There are %s fruits", redis.send!(uint)("SCARD", fruits));

//intelligent opCasts for responses!
if(redis.send("EXISTS", fruits))
    writefln("Fruits have been defined!");

//Lua scripting is supported! ..
Response r1 = redis.eval("return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}", ["key1", "key2"], ["first", "second"]);
writeln(r1); // [key1, key2, first, second]

// .. And pipelining
redis.pipeline(["SET person1:name Adil", "SET person1:name Batman", "SET person1:name Robin"]);

//.. And transactions
redis.transaction(["SET ctr  0", "INCR ctr", "INCR ctr"]);

}

Hangs on empty string responses

To reproduce:

redis-cli
localhost:6379> set test ""
OK
localhost:6379> get test
""
void main()
{
    import tinyredis.redis;
    Redis redis = new Redis;
    Response arr = redis.send("get test");
}

The program will not exit.

Op cast failure for EXISTS

Calls like the below are getting a dmd error saying it can't do Op cast boolean with Response object.
DMD: DMD64 D Compiler v2.066.1

if(redis.send("EXISTS", fruits)) {}

Dub release

First of all thank you for your library.

Can you please release a new dub version that includes #32 and #35?

Thank you

`SCAN` very strange issue

I've this test (database is empty)

unittest {
   auto redis = new Redis();
   int cursor;
   auto response =    redis.send("FLUSHDB");
   do {
      response = redis.send("SCAN", cursor);
      cursor = response.values[0].toInt;
   } while (cursor > 0);
}

then

dub test --debug=tinyredis
No source files found in configuration 'library'. Falling back to "dub -b unittest".
Performing "unittest" build using /usr/bin/dmd for x86_64.
tinyredis 2.1.1: target for configuration "default" is up to date.
tinyredis-test ~master: building configuration "application"...
Linking...
To force a rebuild of up-to-date targets, run again with --force.
Running ./tinyredis-test 
*1\r\n$7\r\nFLUSHDB\r\n
Response : '+OK\r\n' Length : 5
BUFFER : +OK\r\n
*2\r\n$4\r\nSCAN\r\n$1\r\n0\r\n
Response : '*2\r\n$1\r\n0\r\n*0\r\n' Length : 15
BUFFER : *2\r\n$1\r\n0\r\n*0\r\n

..my application freezes.

If I put same code in Tiny-Redis/source/tinyredis/redis.d :

$ make test 
...
...
*1\r\n$7\r\nFLUSHDB\r\n
Response : '+OK\r\n' Length : 5
*2\r\n$4\r\nSCAN\r\n$1\r\n0\r\n
Response : '*2\r\n$1\r\n0\r\n*0\r\n' Length : 15
All unit tests have been run successfully.

it works...

Any suggestion? Thank you

TLS support missing

There doesn't seem to be any TLS support atm. (TLS was added in Redis 6.0.)


I'm going to be adding TLS support to TinyRedis, probably using dub openssl. I'm mostly opening this bug to gather "planning review" type feedback before I start working on a PR.

Current idea is to expand connection.d with interface Transport with class TcpTransport : Transport and class TlsTransport : Transport and just make all the networking code call methods on Transport instead. The whole thing is intended to be hidden behind version (Have_openssl), ie. optional dub openssl dependency, so it shouldn't affect existing users. Then Redis::this just has a new optional parameter to bring up a TLS connection with a certificate.

AUTH stuff can be handled on the userside using sendRaw.

Look good?

Error and semver consideration

I had version 2.2.1, upgraded to 2.3.1 and the compiler complains:

Error: no property `empty` for type `Response`, perhaps `import std.range;` is needed?

In my code the problem is here:

...
auto list = db.send("LRANGE", name, 0, stop);
if (!list.empty) {
   ... 

so, IMHO this is a breaking change, you should increment version to 3.0.0 .... what do you think?

Thank you very much

Error: cannot uniquely infer foreach argument types

I have this code

auto redis_vals = this.redisdb.send("LRANGE", "vals", 0, -1);
writeln(redis_vals); // This prints [val_a, val_b]
foreach (val; redis_vals)
  writeln(val);

it doesn't compile because of Error: cannot uniquely infer foreach argument types.

I'm following the example at http://adilbaig.github.io/Tiny-Redis/

for(fruit; fruits)
  writeln(fruit);

and that also seems wrongly suggesting to use for instead of foreach.

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.