Skip to content

Commit

Permalink
feat: support GET option of the SET command (#455)
Browse files Browse the repository at this point in the history
Towards #450
  • Loading branch information
uki00a authored Oct 21, 2024
1 parent a1d51c0 commit 1672157
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 19 deletions.
10 changes: 8 additions & 2 deletions command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,12 @@ export interface SetOpts {
ex?: number;
px?: number;
keepttl?: boolean;
/**
* Enables `GET` option.
*
* `GET` option was added in Redis v6.2.
*/
get?: boolean;
}

export interface SetWithModeOpts extends SetOpts {
Expand Down Expand Up @@ -327,12 +333,12 @@ export interface RedisCommands {
set(
key: string,
value: RedisValue,
opts?: SetOpts,
opts?: Omit<SetOpts, "get"> & { get?: false | null },
): Promise<SimpleString>;
set(
key: string,
value: RedisValue,
opts?: SetWithModeOpts,
opts?: (Omit<SetOpts, "get"> & { get: true }) | SetWithModeOpts,
): Promise<SimpleString | BulkNil>;
setbit(key: string, offset: number, value: RedisValue): Promise<Integer>;
setex(key: string, seconds: number, value: RedisValue): Promise<SimpleString>;
Expand Down
2 changes: 2 additions & 0 deletions deps/std/testing.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from "jsr:@std/testing@^1.0.0/bdd";
export type * from "jsr:@std/testing@^1.0.0/types";
export { assertType } from "jsr:@std/testing@^1.0.0/types";
20 changes: 15 additions & 5 deletions redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1347,17 +1347,21 @@ class RedisImpl implements Redis {
set(
key: string,
value: RedisValue,
opts?: SetOpts,
opts?: Omit<SetOpts, "get"> & { get?: false | null },
): Promise<SimpleString>;
set(
key: string,
value: RedisValue,
opts?: SetWithModeOpts,
opts?: (Omit<SetOpts, "get"> & { get: true }) | SetWithModeOpts,
): Promise<SimpleString | BulkNil>;
set(
key: string,
value: RedisValue,
opts?: SetOpts | SetWithModeOpts,
opts?:
| (Omit<SetOpts, "get"> & {
get?: true | false | null;
})
| SetWithModeOpts,
) {
const args: RedisValue[] = [key, value];
if (opts?.ex !== undefined) {
Expand All @@ -1368,11 +1372,17 @@ class RedisImpl implements Redis {
if (opts?.keepttl) {
args.push("KEEPTTL");
}
let isAbleToReturnNil = false;
if ((opts as SetWithModeOpts)?.mode) {
args.push((opts as SetWithModeOpts).mode);
return this.execStatusOrNilReply("SET", ...args);
isAbleToReturnNil = true;
}
return this.execStatusReply("SET", ...args);
if (opts?.get) {
args.push("GET");
}
return isAbleToReturnNil
? this.execStatusOrNilReply("SET", ...args)
: this.execStatusReply("SET", ...args);
}

setbit(key: string, offset: number, value: RedisValue) {
Expand Down
52 changes: 40 additions & 12 deletions tests/commands/string.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import { assertEquals } from "../../deps/std/assert.ts";
import { afterAll, beforeAll, beforeEach, it } from "../../deps/std/testing.ts";
import type { IsExact, IsNullable } from "../../deps/std/testing.ts";
import {
afterAll,
assertType,
beforeAll,
beforeEach,
describe,
it,
} from "../../deps/std/testing.ts";
import type { Connector, TestServer } from "../test_util.ts";
import type { Redis } from "../../mod.ts";

Expand Down Expand Up @@ -165,18 +173,38 @@ export function stringTests(
assertEquals(await client.get("key1"), "test");
});

it("set", async () => {
const s = await client.set("key", "fuga你好こんにちは");
assertEquals(s, "OK");
const fuga = await client.get("key");
assertEquals(fuga, "fuga你好こんにちは");
});
describe("set", () => {
it("can set a key", async () => {
const s = await client.set("key", "fuga你好こんにちは");
assertEquals(s, "OK");
assertType<IsExact<typeof s, string>>(true);
const fuga = await client.get("key");
assertEquals(fuga, "fuga你好こんにちは");
});

it("set Number", async () => {
const s = await client.set("key", 123);
assertEquals(s, "OK");
const v = await client.get("key");
assertEquals(v, "123");
it("supports `Number`", async () => {
const s = await client.set("key", 123);
assertEquals(s, "OK");
const v = await client.get("key");
assertEquals(v, "123");
});

it("supports `GET` option", async () => {
const prev = "foobar";
await client.set("setWithGetOpt", prev);
const result = await client.set("setWithGetOpt", "baz", { get: true });
assertEquals(result, prev);
assertType<IsNullable<typeof result>>(true);
});

it("supports `NX` option", async () => {
const prev = "foo";
const v1 = await client.set("setWithNX", prev, { mode: "NX" });
assertEquals(v1, "OK");
const v2 = await client.set("setWithNX", "bar", { mode: "NX" });
assertEquals(v2, null);
assertType<IsNullable<typeof v2>>(true);
});
});

it("setbit", async () => {
Expand Down

0 comments on commit 1672157

Please sign in to comment.