migueldeicaza/redis-sharp — pull request #7 by rfranke (2014-08-16 19:29:00+00:00)
Title: Introduce REdis Serial Protocol (RESP) to fix open issues

I want to add a simple Redis client to a larger existing software component that still uses .NET 2.0. RedisSharp is out-standing in fitting into one source file and not relying on advanced features such as generics or the lambda operator.

There are some small issues though. This pull request basically upgrades the communication to RESP (REdis Serial Protocol), which was introduced with Redis 1.2 and became standard with Redis 2.0. This solves the open issues #1, #3 and #6.

***#6 Set fails***

The RedisTest program fails with Redis 2.8 and Redis 2.4 already with the first command (test.cs, line 16):
```
SET foo bar
```
It appears that newer Redis servers don't support inline commands with data bytes on a separate line anymore.
```
S: SET foo 3
S: bar
```
sets `foo` to `3` and raises an error for the unknown command `bar`. In fact such inline commands with raw data are not mentioned in the current Redis protocol specification (http://redis.io/topics/protocol).

The console log doesn't really tell what's going on:
```
$ RedisTest/bin/Debug/RedisTest
S: SET foo 3
+OK
S: FLUSHALL
S: KEYS *
R: +OK

Unhandled Exception: Redis+ResponseException: Response error
```
This is why the first commit shall improve the error messages. Some calls of simple Redis commands, like FLUSHALL, were done with SendGetString, ignoring the return value. They call SendExpectSuccess now. This changes the console output to:
```
$ RedisTest/bin/Debug/RedisTest
S: SET foo 3
+OK
S: FLUSHALL
-ERR unknown command 'bar'

Unhandled Exception: Redis+ResponseException: Response error
```

The second commit changes the protocol to RESP for commands that send data. This fixes the issue with Set.

The Log method replaces "\r\n" with " " to get more readable log messages.

***#1 keys containing spaces***

The third commit introduces RESP for all commands. Keys may use arbitrary characters this way.

The fourth commit adds raw byte versions for LeftPush and RighPush and it complements LeftPop with the corresponding RightPop.

***#3 GetKeys fails with more than one key***

The fifth commit fixes GetKeys and ReadData. ReadData with return type byte[] only supports one array element -- there should be no array parsing in this function, because it breaks the client in the case of arrays with more than one element. GetKeys now calls SendDataCommandExpectMultiBuldReply to receive an arbitray number of keys.

Moreover, I renamed the second GetKeys method to MGet, in order to make clear that it doesn't return keys like the first GetKeys, but values obtained with Redis MGET.

The extended RedisTest covers a key with space and multiple keys.

***Finally***

Please allow me a sixth commit that replaces `var` with explicit types. This simplifies downgrading to .NET 2 and it improves the understanding of the code (e.g. string for keys vs. byte[] for values).

Last but not least the seventh commit fixes the call to ResponseException if Redis just returns "-ERR" -- this was seen with MSOpenTech's Redis 2.8.9, where the server crashed when the client called BGSAVE (otherwise the tests pass).

The updates have been tested with the current Redis 2.8 and with an older Redis 2.4. The tests pass without problem under Linux.