Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 0 additions & 66 deletions .github/dependabot.yml

This file was deleted.

39 changes: 38 additions & 1 deletion deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions pkg/commands/json_get.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ Deno.test("Return the value at path in JSON serialized form", async () => {
assertEquals(res1, "OK");
const res2 = await new JsonGetCommand([key, "$..b"]).exec(client);
assertEquals(res2, [null, 3]);
const res3 = await new JsonGetCommand([key, "..a", "$..b"]).exec(client);
assertEquals(res3, { "$..b": [null, 3], "..a": [4, 2] });
const res3 = await new JsonGetCommand([key, "$..a", "$..b"]).exec(client);
assertEquals(res3, { "$..b": [null, 3], "$..a": [4, 2] });
});
1 change: 1 addition & 0 deletions pkg/commands/mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ export * from "./touch.ts";
export * from "./ttl.ts";
export * from "./type.ts";
export * from "./unlink.ts";
export * from "./xadd.ts";
export * from "./zadd.ts";
export * from "./zcard.ts";
export * from "./zcount.ts";
Expand Down
125 changes: 125 additions & 0 deletions pkg/commands/xadd.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { assert } from "https://deno.land/[email protected]/testing/asserts.ts";
import { keygen, newHttpClient, randomID } from "../test-utils.ts";

import { afterAll } from "https://deno.land/[email protected]/testing/bdd.ts";
import { XAddCommand } from "./xadd.ts";
import { XRangeCommand } from "./xrange.ts";

const client = newHttpClient();

const { newKey, cleanup } = keygen();
afterAll(cleanup);

Deno.test("without options", async (t) => {
await t.step("should return valid stream id", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

const res = await new XAddCommand([key, "*", {
[field1]: member1,
[field2]: member2,
}]).exec(
client,
);

assert(res.length > 0);
});
});

Deno.test("with NOMKSTREAM", async (t) => {
await t.step("should return valid stream id", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

const first = await new XAddCommand([key, "*", {
[field1]: member1,
[field2]: member2,
}]).exec(
client,
);
assert(first.length > 0);

const res = await new XAddCommand([
key,
"*",
{ [field1]: member1, [field2]: member2 },
{ nomkStream: true },
]).exec(client);
assert(res.length > 0);
});

await t.step("should return null", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

const res = await new XAddCommand([
key,
"*",
{ [field1]: member1, [field2]: member2 },
{ nomkStream: true },
]).exec(client);

assert(res === null);
});
});

Deno.test("with threshold", async (t) => {
await t.step("should always return less than or equal to 5", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

for (let i = 0; i < 10; i++) {
const xaddRes = await new XAddCommand([
key,
"*",
{ [field1]: member1, [field2]: member2 },
{ trim: { comparison: "=", threshold: 5, type: "MAXLEN" } },
]).exec(client);
assert(xaddRes.length > 0);

const xrangeRes = await new XRangeCommand([key, "-", "+"]).exec(client);
assert(Object.keys(xrangeRes).length <= 5);
}
});

await t.step("should trim the stream by stream id", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

const xaddRes = await new XAddCommand([
key,
"*",
{ [field1]: member1, [field2]: member2 },
]).exec(client);

await new XAddCommand([
key,
"*",
{ [field1]: member1, [field2]: member2 },
{ trim: { type: "minid", threshold: xaddRes, comparison: "=" } },
]).exec(client);

const xrangeRes = await new XRangeCommand([key, "-", "+"]).exec(client);
assert(Object.keys(xrangeRes).length === 1);
});
});
64 changes: 64 additions & 0 deletions pkg/commands/xadd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Command, CommandOptions } from "./command.ts";

type XAddCommandOptions = {
nomkStream?: boolean;
trim?:
& (
| {
type: "MAXLEN" | "maxlen";
threshold: number;
}
| {
type: "MINID" | "minid";
threshold: string;
}
)
& (
| {
comparison: "~";
limit?: number;
}
| {
comparison: "=";
limit?: never;
}
);
};

/**
* @see https://redis.io/commands/xadd
*/
export class XAddCommand extends Command<string, string> {
constructor(
[key, id, entries, opts]: [
key: string,
id: "*" | string,
entries: { [field: string]: unknown },
opts?: XAddCommandOptions,
],
commandOptions?: CommandOptions<string, string>,
) {
const command: unknown[] = ["XADD", key];

if (opts) {
if (opts.nomkStream) {
command.push("NOMKSTREAM");
}
if (opts.trim) {
command.push(opts.trim.type, opts.trim.comparison, opts.trim.threshold);
if (typeof opts.trim.limit !== "undefined") {
command.push("LIMIT", opts.trim.limit);
}
}
}

command.push(id);

// entries
Object.entries(entries).forEach(([k, v]) => {
command.push(k, v);
});

super(command, commandOptions);
}
}
52 changes: 52 additions & 0 deletions pkg/commands/xrange.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { assertEquals } from "https://deno.land/[email protected]/testing/asserts.ts";
import { keygen, newHttpClient, randomID } from "../test-utils.ts";

import { afterAll } from "https://deno.land/[email protected]/testing/bdd.ts";
import { XAddCommand } from "./xadd.ts";
import { XRangeCommand } from "./xrange.ts";

const client = newHttpClient();

const { newKey, cleanup } = keygen();
afterAll(cleanup);

Deno.test("without options", async (t) => {
await t.step("returns the set", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

await new XAddCommand([key, "*", { [field1]: member1, [field2]: member2 }])
.exec(client);

const res = await new XRangeCommand([key, "-", "+"]).exec(client);
assertEquals(Object.keys(res).length, 1);
assertEquals(Object.values(res)[0], {
[field1]: member1,
[field2]: member2,
});
});
});

Deno.test("limit", async (t) => {
await t.step("returns the only the first one", async () => {
const key = newKey();
const field1 = "field1";
const member1 = randomID();

const field2 = "field2";
const member2 = randomID();

await new XAddCommand([key, "*", { [field1]: member1 }]).exec(client);
await new XAddCommand([key, "*", { [field2]: member2 }]).exec(client);

const res = await new XRangeCommand([key, "-", "+", 1]).exec(client);
assertEquals(Object.keys(res).length, 1);
assertEquals(Object.values(res)[0], {
[field1]: member1,
});
});
});
Loading