Skip to content

Commit

Permalink
chore: minor tweaks and simplifications
Browse files Browse the repository at this point in the history
  • Loading branch information
iuioiua committed Jul 26, 2022
1 parent c6ae216 commit d88c30e
Showing 3 changed files with 110 additions and 92 deletions.
23 changes: 9 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -11,33 +11,28 @@ Lightweight Redis client library for Deno. Design principles:

Must be run with `--allow-net` permission.

### Basic commands
### Single command

```ts
import { sendCommand } from "https://deno.land/x/r2d2/mod.ts";

const redisConn = await Deno.connect({ port: 6379 }); // Connect to the Redis server

await sendCommand(redisConn, ["SET", "hello", "world"]); // Returns "OK"

await sendCommand(redisConn, ["GET", "hello"]); // Returns "world"

redisConn.close(); // Close the connection to the Redis server
```
const redisConn = await Deno.connect({ port: 6379 });

If you'd like to ignore the reply.
// Returns "OK"
await sendCommand(redisConn, ["SET", "hello", "world"]);

```ts
await sendCommand(redis, ["SHUTDOWN"], false); // Returns nothing
// Returns "world"
await sendCommand(redisConn, ["GET", "hello"]);
```

### Pipelining
### Multiple commands (pipelining)

```ts
import { pipelineCommands } from "https://deno.land/x/r2d2/mod.ts";

const redisConn = await Deno.connect({ port: 6379 }); // Connect to the Redis server
const redisConn = await Deno.connect({ port: 6379 });

// Returns [1, 2, 3, 4]
await pipelineCommands(redisConn, [
["INCR", "X"],
["INCR", "X"],
7 changes: 4 additions & 3 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@ function createRequest(command: Command): string {
return request;
}

/** Encodes and sends the request string to the server. */
async function writeRequest(
redisConn: Deno.Conn,
request: string,
@@ -106,9 +105,11 @@ async function readReply(bufReader: BufReader): Promise<Reply> {
* ```ts
* const redisConn = await Deno.connect({ port: 6379 });
*
* await sendCommand(redisConn, ["SET", "hello", "world"]); // Returns "OK"
* // Returns "OK"
* await sendCommand(redisConn, ["SET", "hello", "world"]);
*
* await sendCommand(redisConn, ["GET", "hello"]); // Returns "world"
* // Returns "world"
* await sendCommand(redisConn, ["GET", "hello"]);
* ```
*/
export async function sendCommand(
172 changes: 97 additions & 75 deletions test.ts
Original file line number Diff line number Diff line change
@@ -1,95 +1,117 @@
import { assertEquals, assertRejects } from "./deps.ts";
import {
type Command,
listenReplies,
pipelineCommands,
type Reply,
sendCommand,
writeCommand,
} from "./mod.ts";
import { REDIS_PORT, SERVER_PROCESS } from "./_util.ts";

Deno.test("sendCommand and pipelineCommands", async (t) => {
await SERVER_PROCESS.status();
const redisConn = await Deno.connect({ port: REDIS_PORT });

async function flushDB() {
await sendCommand(redisConn, ["FLUSHDB"]);
}

async function sendCommandTest(
command: Command,
expected: Reply,
): Promise<void> {
assertEquals(await sendCommand(redisConn, command), expected);
}

await flushDB();

await t.step("parses simple string", async () => {
await sendCommandTest(["PING"], "PONG");
});

await t.step("parses error", () => {
assertRejects(async () => await sendCommand(redisConn, ["helloworld"]));
});

await t.step("parses integer", async () => {
await sendCommandTest(["INCR", "integer"], 1);
await sendCommandTest(["INCR", "integer"], 2);
});

await t.step("parses bulk string", async () => {
await sendCommand(redisConn, ["SET", "big ups", "west side massive"]);
await sendCommandTest(["GET", "big ups"], "west side massive");
});

await t.step("parses null", async () => {
await sendCommandTest(["GET", "nonexistant"], null);
});

await t.step("parses array", async () => {
await sendCommand(redisConn, [
"HSET",
"hash",
"hello",
"world",
"integer",
13,
]);
await sendCommandTest([
"HMGET",
"hash",
"hello",
"integer",
"nonexistant",
], ["world", "13", null]);
});

await t.step("parses empty array", async () => {
await sendCommandTest(["HGETALL", "nonexistant"], []);
});

await t.step("parses null array", async () => {
await sendCommandTest(["BLPOP", "list", 1], null);
});

await t.step("transactions work", async () => {
await sendCommandTest(["MULTI"], "OK");
await sendCommandTest(["INCR", "FOO"], "QUEUED");
await sendCommandTest(["INCR", "BAR"], "QUEUED");
await sendCommandTest(["EXEC"], [1, 1]);
});

await t.step("pipelining works", async () => {
async function flushDB(redisConn: Deno.Conn): Promise<void> {
await sendCommand(redisConn, ["FLUSHDB"]);
}

Deno.test({
name: "sendCommand",
async fn(t) {
await SERVER_PROCESS.status();
const redisConn = await Deno.connect({ port: REDIS_PORT });

async function sendCommandTest(
command: Command,
expected: Reply,
): Promise<void> {
assertEquals(await sendCommand(redisConn, command), expected);
}

await flushDB(redisConn);

await t.step("parses simple string", async () => {
await sendCommandTest(["PING"], "PONG");
});

await t.step("parses error", () => {
assertRejects(async () => await sendCommand(redisConn, ["helloworld"]));
});

await t.step("parses integer", async () => {
await sendCommandTest(["INCR", "integer"], 1);
await sendCommandTest(["INCR", "integer"], 2);
});

await t.step("parses bulk string", async () => {
await sendCommand(redisConn, ["SET", "big ups", "west side massive"]);
await sendCommandTest(["GET", "big ups"], "west side massive");
});

await t.step("parses null", async () => {
await sendCommandTest(["GET", "nonexistant"], null);
});

await t.step("parses array", async () => {
await sendCommand(redisConn, [
"HSET",
"hash",
"hello",
"world",
"integer",
13,
]);
await sendCommandTest([
"HMGET",
"hash",
"hello",
"integer",
"nonexistant",
], ["world", "13", null]);
});

await t.step("parses empty array", async () => {
await sendCommandTest(["HGETALL", "nonexistant"], []);
});

await t.step("parses null array", async () => {
await sendCommandTest(["BLPOP", "list", 1], null);
});

await t.step("transactions work", async () => {
await sendCommandTest(["MULTI"], "OK");
await sendCommandTest(["INCR", "FOO"], "QUEUED");
await sendCommandTest(["INCR", "BAR"], "QUEUED");
await sendCommandTest(["EXEC"], [1, 1]);
});

await flushDB(redisConn);
redisConn.close();
},
});

Deno.test({
name: "pipelineCommands",
async fn() {
await SERVER_PROCESS.status();
const redisConn = await Deno.connect({ port: REDIS_PORT });

await flushDB(redisConn);

assertEquals(
await pipelineCommands(redisConn, [
["INCR", "X"],
["INCR", "X"],
["INCR", "X"],
["INCR", "X"],
["SET", "hello", "world"],
["GET", "hello"],
]),
[1, 2, 3, 4],
[1, 2, 3, 4, "OK", "world"],
);
});

await flushDB(redisConn);
redisConn.close();
},
});

Deno.test({
name: "listenReplies",

0 comments on commit d88c30e

Please sign in to comment.