Skip to content

Commit

Permalink
added sadd, srem, smembers and scard in node
Browse files Browse the repository at this point in the history
  • Loading branch information
Adan committed Oct 17, 2023
1 parent 72f7564 commit eae915a
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 0 deletions.
51 changes: 51 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import {
createIncrByFloat,
createMGet,
createMSet,
createSAdd,
createSCard,
createSMembers,
createSRem,
createSet,
} from "./Commands";
import {
Expand Down Expand Up @@ -518,6 +522,53 @@ export class BaseClient {
return this.createWritePromise(createHIncrByFloat(key, field, amount));
}

/** Adds the specified members to the set stored at `key`. Specified members that are already a member of this set are ignored.
* If `key` does not exist, a new set is created before adding `members`.
* See https://redis.io/commands/sadd/ for details.
*
* @param key - The key to store the members to its set.
* @param members - A list of members to add to the set stored at `key`.
* @returns the number of members that were added to the set, not including all the members already present in the set.
* If `key` holds a value that is not a set, an error is returned.
*/
public sadd(key: string, members: string[]): Promise<number> {
return this.createWritePromise(createSAdd(key, members));
}

/** Removes the specified members from the set stored at `key`. Specified members that are not a member of this set are ignored.
* See https://redis.io/commands/srem/ for details.
*
* @param key - The key to remove the members from its set.
* @param members - A list of members to remove from the set stored at `key`.
* @returns the number of members that were removed from the set, not including non existing members.
* If `key` does not exist, it is treated as an empty set and this command returns 0.
* If `key` holds a value that is not a set, an error is returned.
*/
public srem(key: string, members: string[]): Promise<number> {
return this.createWritePromise(createSRem(key, members));
}

/** Returns all the members of the set value stored at `key`.
* See https://redis.io/commands/smembers/ for details.
*
* @param key - The key to return its members.
* @returns all members of the set. If `key` holds a value that is not a set, an error is returned.
*/
public smembers(key: string): Promise<string[]> {
return this.createWritePromise(createSMembers(key));
}

/** Returns the set cardinality (number of elements) of the set stored at `key`.
* See https://redis.io/commands/scard/ for details.
*
* @param key - The key to return the number of its members.
* @returns the cardinality (number of elements) of the set, or 0 if key does not exist.
* If `key` holds a value that is not a set, an error is returned.
*/
public scard(key: string): Promise<number> {
return this.createWritePromise(createSCard(key));
}

private readonly MAP_READ_FROM_REPLICA_STRATEGY: Record<
ReadFromReplicaStrategy,
connection_request.ReadFromReplicaStrategy
Expand Down
22 changes: 22 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,28 @@ export function createHGetAll(key: string): redis_request.Command {
return createCommand(RequestType.HashGetAll, [key]);
}

export function createSAdd(
key: string,
members: string[]
): redis_request.Command {
return createCommand(RequestType.SAdd, [key].concat(members));
}

export function createSRem(
key: string,
members: string[]
): redis_request.Command {
return createCommand(RequestType.SRem, [key].concat(members));
}

export function createSMembers(key: string): redis_request.Command {
return createCommand(RequestType.SMembers, [key]);
}

export function createSCard(key: string): redis_request.Command {
return createCommand(RequestType.SCard, [key]);
}

export function createCustomCommand(commandName: string, args: string[]) {
return createCommand(RequestType.CustomCommand, [commandName, ...args]);
}
Expand Down
55 changes: 55 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ import {
createMGet,
createMSet,
createPing,
createSAdd,
createSCard,
createSMembers,
createSRem,
createSelect,
createSet,
} from "./Commands";
Expand Down Expand Up @@ -378,6 +382,57 @@ export class BaseTransaction {
this.commands.push(createHIncrByFloat(key, field, amount));
}

/** Adds the specified members to the set stored at `key`. Specified members that are already a member of this set are ignored.
* If `key` does not exist, a new set is created before adding `members`.
* See https://redis.io/commands/sadd/ for details.
*
* @param key - The key to store the members to its set.
* @param members - A list of members to add to the set stored at `key`.
*
* Command Response - the number of members that were added to the set, not including all the members already present in the set.
* If `key` holds a value that is not a set, an error is returned.
*/
public sadd(key: string, members: string[]) {
this.commands.push(createSAdd(key, members));
}

/** Removes the specified members from the set stored at `key`. Specified members that are not a member of this set are ignored.
* See https://redis.io/commands/srem/ for details.
*
* @param key - The key to remove the members from its set.
* @param members - A list of members to remove from the set stored at `key`.
*
* Command Response - the number of members that were removed from the set, not including non existing members.
* If `key` does not exist, it is treated as an empty set and this command returns 0.
* If `key` holds a value that is not a set, an error is returned.
*/
public srem(key: string, members: string[]) {
this.commands.push(createSRem(key, members));
}

/** Returns all the members of the set value stored at `key`.
* See https://redis.io/commands/smembers/ for details.
*
* @param key - The key to return its members.
*
* Command Response - all members of the set. If `key` holds a value that is not a set, an error is returned.
*/
public smembers(key: string) {
this.commands.push(createSMembers(key));
}

/** Returns the set cardinality (number of elements) of the set stored at `key`.
* See https://redis.io/commands/scard/ for details.
*
* @param key - The key to return the number of its members.
*
* Command Response - the cardinality (number of elements) of the set, or 0 if key does not exist.
* If `key` holds a value that is not a set, an error is returned.
*/
public scard(key: string) {
this.commands.push(createSCard(key));
}

/** Executes a single command, without checking inputs. Every part of the command, including subcommands,
* should be added as a separate value in args.
*
Expand Down
82 changes: 82 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ type BaseClient = {
field: string,
amount: number
) => Promise<string>;
sadd: (key: string, members: string[]) => Promise<number>;
srem: (key: string, members: string[]) => Promise<number>;
smembers: (key: string) => Promise<string[]>;
scard: (key: string) => Promise<number>;
customCommand: (commandName: string, args: string[]) => Promise<ReturnType>;
};

Expand Down Expand Up @@ -692,6 +696,84 @@ export function runBaseTests<Context>(config: {
},
config.timeout
);

it(
"sadd, srem, scard and smembers with existing key",
async () => {
await runTest(async (client: BaseClient) => {
const key = uuidv4();
const valueList = ["member1", "member2", "member3", "member4"];
expect(await client.sadd(key, valueList)).toEqual(4);
expect(
await client.srem(key, ["member3", "nonExistingMember"])
).toEqual(1);
/// compare the 2 sets.
expect(await client.smembers(key)).toEqual(
expect.arrayContaining(["member1", "member2", "member4"])
);
expect(await client.srem(key, ["member1"])).toEqual(1);
expect(await client.scard(key)).toEqual(2);
});
},
config.timeout
);

it(
"srem, scard and smembers with non existing key",
async () => {
await runTest(async (client: BaseClient) => {
expect(await client.srem("nonExistingKey", ["member"])).toEqual(
0
);
expect(await client.scard("nonExistingKey")).toEqual(0);
expect(await client.smembers("nonExistingKey")).toEqual([]);
});
},
config.timeout
);

it(
"sadd, srem, scard and smembers with with key that holds a value that is not a set",
async () => {
await runTest(async (client: BaseClient) => {
const key = uuidv4();
expect(await client.set(key, "foo")).toEqual("OK");

try {
expect(await client.sadd(key, ["bar"])).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"Operation against a key holding the wrong kind of value"
);
}

try {
expect(await client.srem(key, ["bar"])).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"Operation against a key holding the wrong kind of value"
);
}

try {
expect(await client.scard(key)).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"Operation against a key holding the wrong kind of value"
);
}

try {
expect(await client.smembers(key)).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"Operation against a key holding the wrong kind of value"
);
}
});
},
config.timeout
);
}

export function runCommonTests<Context>(config: {
Expand Down
9 changes: 9 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export function transactionTest(
const key2 = "{key}" + uuidv4();
const key3 = "{key}" + uuidv4();
const key4 = "{key}" + uuidv4();
const key5 = "{key}" + uuidv4();
const field = uuidv4();
const value = uuidv4();
baseTransaction.set(key1, "bar");
Expand All @@ -70,6 +71,10 @@ export function transactionTest(
baseTransaction.hdel(key4, [field]);
baseTransaction.hmget(key4, [field]);
baseTransaction.hexists(key4, field);
baseTransaction.sadd(key5, ["bar", "foo"]);
baseTransaction.srem(key5, ["foo"]);
baseTransaction.scard(key5);
baseTransaction.smembers(key5);
return [
"OK",
null,
Expand All @@ -83,5 +88,9 @@ export function transactionTest(
1,
[null],
0,
2,
1,
1,
["bar"]
];
}

0 comments on commit eae915a

Please sign in to comment.