Permalink
Browse files

Added redis-node-client.

  • Loading branch information...
1 parent 9a4919f commit 79f702e065545813259e59d3d29377f93a26fe28 Jonas Galvez committed Aug 31, 2010
@@ -0,0 +1 @@
+*.swp
@@ -0,0 +1,19 @@
+© 2010 by Fictorial LLC
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
@@ -0,0 +1,103 @@
+# Redis client for Node.js
+
+## In a nutshell
+
+- Talk to Redis from Node.js
+- Fully asynchronous; your code is called back when an operation completes
+- [Binary-safe](http://github.com/fictorial/redis-node-client/blob/master/test/test.js#L353-363); uses Node.js Buffer objects for request serialization and reply parsing
+ - e.g. store a PNG in Redis if you'd like
+- Client API directly follows Redis' [command specification](http://code.google.com/p/redis/wiki/CommandReference)
+- *You have to understand how Redis works and the semantics of its command set to most effectively use this client*
+- Supports Redis' new exciting [PUBSUB](http://code.google.com/p/redis/wiki/PublishSubscribe) commands
+- Automatically reconnects to Redis (doesn't drop commands sent while waiting to reconnect either) using [exponential backoff](http://en.wikipedia.org/wiki/Exponential_backoff)
+ - Be sure to see [this script](http://github.com/fictorial/redis-node-client/blob/master/test/test_shutdown_reconnect.js) for a deeper discussion
+
+## Synopsis
+
+When working from a git clone:
+
+ var sys = require("sys");
+ var client = require("../lib/redis-client").createClient();
+ client.info(function (err, info) {
+ if (err) throw new Error(err);
+ sys.puts("Redis Version is: " + info.redis_version);
+ client.close();
+ });
+
+When working with a Kiwi-based installation:
+
+ // $ kiwi install redis-client
+
+ var sys = require("sys"),
+ kiwi = require("kiwi"),
+ client = kiwi.require("redis-client").createClient();
+
+ client.info(function (err, info) {
+ if (err) throw new Error(err);
+ sys.puts("Redis Version is: " + info.redis_version);
+ client.close();
+ });
+
+- Refer to the many tests in `test/test.js` for many usage examples.
+- Refer to the `examples/` directory for focused examples.
+
+## Installation
+
+This version requires at least `Node.js v0.1.90` and Redis `1.3.8`.
+
+Tested with Node.js `v0.1.95` and `v0.1.96` and Redis `2.1.1` (the current unstable).
+
+You have a number of choices:
+
+- git clone this repo or download a tarball and simply copy `lib/redis-client.js` into your project
+- use git submodule
+- use the [Kiwi](http://github.com/visionmedia/kiwi) package manager for Node.js
+
+Please let me know if the package manager "seeds" and/or metadata have issues.
+Installation via Kiwi or NPM at this point isn't really possible since this repo
+depends on a unreleased version of Node.js.
+
+## Running the tests
+
+A good way to learn about this client is to read the test code.
+
+To run the tests, install and run redis on the localhost on port 6379 (defaults).
+Then run `node test/test.js [-v|-q]` where `-v` is for "verbose" and `-q` is for "quiet".
+
+ $ node test/test.js
+ ..................................................................
+ ...........................++++++++++++++++++++++++++++++++++++
+
+ [INFO] All tests have passed.
+
+If you see something like "PSUBSCRIBE: unknown command" then it is time to upgrade
+your Redis installation.
+
+## Documentation
+
+There is a method per Redis command. E.g. `SETNX` becomes `client.setnx`.
+
+For example, the Redis command [INCRBY](http://code.google.com/p/redis/wiki/IncrCommand)
+is specified as `INCRBY key integer`. Also, the INCRBY spec says that the reply will
+be "... the new value of key after the increment or decrement."
+
+This translates to the following client code which increments key 'foo' by 42. If
+the value at key 'foo' was 0 or non-existent, 'newValue' will take value 42 when
+the callback function is called.
+
+ client.incrby('foo', 42, function (err, newValue) {
+ // ...
+ });
+
+This can get [a little wacky](http://github.com/fictorial/redis-node-client/blob/master/test/test.js#L1093-1097).
+I'm open to suggestions for improvement here.
+
+Note: for PUBSUB, you should use `subscribeTo` and `unsubscribeFrom` instead of the generated
+methods for Redis' `SUBSCRIBE` and `UNSUBSCRIBE` commands. See [this](http://github.com/fictorial/redis-node-client/blob/master/lib/redis-client.js#L682-694)
+and [this](http://github.com/fictorial/redis-node-client/blob/master/examples/subscriber.js#L14).
+
+## Notes
+
+All commands/requests use the Redis *multi-bulk request* format which will be
+the only accepted request protocol come Redis 2.0.
+
@@ -0,0 +1,23 @@
+## Soon
+
+- Support MULTI/EXEC/DISCARD. This is a little tricky given that its
+ referred to as a "transaction" (but it's really a macro). The API
+ must clearly define what the hell is going on in error cases, etc.
+ Also, we'll need to add support for nested multi-bulk replies. The
+ reply parser, while it handles non-bulk replies inside a multi-bulk
+ reply, does not handle multi-bulk replies inside multi-bulk replies.
+ This is required for MULTI/EXEC.
+
+- WATCH support
+
+- Now that Node.js has UDP support and Redis 2.0 will have UDP support,
+ I suppose we should add, you know, UDP support here.
+
+## Later
+
+- Provide wrapper around the pretty-raw sort method?
+
+## Maybe
+
+- Add support for consistent hashing ala redis-rb and txRedisAPI
+- Add a higher-level interface similar to Ohm (Ruby)
@@ -0,0 +1,32 @@
+## Some examples.
+
+Note: a large number of usage examples can be found in `../test/test.js`.
+
+## Publisher-Subscriber (PUBSUB)
+
+In one terminal:
+
+ $ ./publisher.js
+ Published message to no one.
+ Published message to no one.
+ Published message to no one.
+ Published message to 1 subscriber(s). <-- Started the subscriber.
+ Published message to 1 subscriber(s).
+ Published message to 1 subscriber(s).
+ Published message to 1 subscriber(s).
+ Published message to no one. <-- Killed (^C) the subscriber.
+ ^C
+
+In another terminal:
+
+ $ ./subscriber.js
+ waiting for messages...
+ [channel-6702921148389578]: The time is Fri Apr 02 2010 16:52:19 GMT-0400 (EDT)
+ [channel-9212789069861174]: The time is Fri Apr 02 2010 16:52:20 GMT-0400 (EDT)
+ [channel-30327219143509865]: The time is Fri Apr 02 2010 16:52:21 GMT-0400 (EDT)
+ [channel-35810230672359467]: The time is Fri Apr 02 2010 16:52:22 GMT-0400 (EDT)
+ [channel-5208229701966047]: The time is Fri Apr 02 2010 16:52:23 GMT-0400 (EDT)
+ [channel-26559297926723957]: The time is Fri Apr 02 2010 16:52:24 GMT-0400 (EDT)
+ [channel-9280104916542768]: The time is Fri Apr 02 2010 16:52:25 GMT-0400 (EDT)
+ ^C
+
@@ -0,0 +1,21 @@
+#!/usr/bin/env node
+
+// This script plays the role of publisher.
+
+var
+ sys = require("sys"),
+ client = require("../lib/redis-client").createClient();
+
+// Publish a message once a second to a random channel.
+
+setInterval(function () {
+ var
+ channelName = "channel-" + Math.random().toString().substr(2),
+ payload = "The time is " + (new Date());
+
+ client.publish(channelName, payload,
+ function (err, reply) {
+ sys.puts("Published message to " +
+ (reply === 0 ? "no one" : (reply + " subscriber(s).")));
+ });
+}, 1000);
@@ -0,0 +1,7 @@
+var sys = require("sys");
+var client = require("../lib/redis-client").createClient();
+client.info(function (err, info) {
+ if (err) throw new Error(err);
+ sys.puts("Redis Version is: " + info.redis_version);
+ client.close();
+});
@@ -0,0 +1,19 @@
+#!/usr/bin/env node
+
+// This script plays the role of listener/subscriber/consumer
+// to **all** channels/classes.
+
+var
+ sys = require("sys"),
+ client = require("../lib/redis-client").createClient();
+
+sys.puts("waiting for messages...");
+
+client.subscribeTo("*",
+ function (channel, message, subscriptionPattern) {
+ var output = "[" + channel;
+ if (subscriptionPattern)
+ output += " (from pattern '" + subscriptionPattern + "')";
+ output += "]: " + message;
+ sys.puts(output);
+ });
@@ -0,0 +1,16 @@
+// Kiwi is a package manager for Node.js
+// http://wiki.github.com/visionmedia/kiwi/getting-started
+//
+// $ kiwi install redis-client
+
+var sys = require("sys"),
+ kiwi = require("kiwi"),
+ client = kiwi.require("redis-client").createClient();
+
+client.stream.addListener("connect", function () {
+ client.info(function (err, info) {
+ if (err) throw new Error(err);
+ sys.puts("Redis Version is: " + info.redis_version);
+ client.close();
+ });
+});
Oops, something went wrong.

0 comments on commit 79f702e

Please sign in to comment.