Skip to content

Commit

Permalink
Node: added spop and spopCount commands. (valkey-io#1117)
Browse files Browse the repository at this point in the history
Co-authored-by: Shoham Elias <[email protected]>
  • Loading branch information
adanWattad and shohamazon authored Apr 9, 2024
1 parent 5395fe1 commit 78cfa33
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Python: Added STRLEN command ([#1230](https:/aws/glide-for-redis/pull/1230))
* Python: Added HKEYS command ([#1228](https:/aws/glide-for-redis/pull/1228))
* Python: Added ZREMRANGEBYSCORE command ([#1151](https:/aws/glide-for-redis/pull/1151))
* Node: Added SPOP, SPOPCOUNT commands. ([#1117](https:/aws/glide-for-redis/pull/1117))

#### Fixes
* Python: Fix typing error "‘type’ object is not subscriptable" ([#1203](https:/aws/glide-for-redis/pull/1203))
Expand Down
1 change: 1 addition & 0 deletions glide-core/src/protobuf/redis_request.proto
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ enum RequestType {
DBSize = 92;
Brpop = 93;
Hkeys = 94;
Spop = 95;
PfAdd = 96;
PfCount = 97;
PfMerge = 98;
Expand Down
3 changes: 3 additions & 0 deletions glide-core/src/request_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ pub enum RequestType {
DBSize = 92,
Brpop = 93,
Hkeys = 94,
Spop = 95,
PfAdd = 96,
PfCount = 97,
PfMerge = 98,
Expand Down Expand Up @@ -223,6 +224,7 @@ impl From<::protobuf::EnumOrUnknown<ProtobufRequestType>> for RequestType {
ProtobufRequestType::RPushX => RequestType::RPushX,
ProtobufRequestType::LPushX => RequestType::LPushX,
ProtobufRequestType::Blpop => RequestType::Blpop,
ProtobufRequestType::Spop => RequestType::Spop,
}
}
}
Expand Down Expand Up @@ -332,6 +334,7 @@ impl RequestType {
RequestType::RPushX => Some(cmd("RPUSHX")),
RequestType::LPushX => Some(cmd("LPUSHX")),
RequestType::Blpop => Some(cmd("BLPOP")),
RequestType::Spop => Some(cmd("SPOP")),
}
}
}
25 changes: 25 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import {
createSAdd,
createSCard,
createSMembers,
createSPop,
createSRem,
createSet,
createSismember,
Expand Down Expand Up @@ -1234,6 +1235,30 @@ export class BaseClient {
return this.createWritePromise(createSismember(key, member));
}

/** Removes and returns one random member from the set value store at `key`.
* See https://redis.io/commands/spop/ for details.
* To pop multiple members, see `spopCount`.
*
* @param key - The key of the set.
* @returns the value of the popped member.
* If `key` does not exist, null will be returned.
*/
public spop(key: string): Promise<string | null> {
return this.createWritePromise(createSPop(key));
}

/** Removes and returns up to `count` random members from the set value store at `key`, depending on the set's length.
* See https://redis.io/commands/spop/ for details.
*
* @param key - The key of the set.
* @param count - The count of the elements to pop from the set.
* @returns A list of popped elements will be returned depending on the set's length.
* If `key` does not exist, empty list will be returned.
*/
public spopCount(key: string, count: number): Promise<string[]> {
return this.createWritePromise(createSPop(key, count));
}

/** Returns the number of keys in `keys` that exist in the database.
* See https://redis.io/commands/exists/ for details.
*
Expand Down
8 changes: 8 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,14 @@ export function createSismember(
return createCommand(RequestType.SIsMember, [key, member]);
}

/**
* @internal
*/
export function createSPop(key: string, count?: number): redis_request.Command {
const args: string[] = count == undefined ? [key] : [key, count.toString()];
return createCommand(RequestType.Spop, args);
}

/**
* @internal
*/
Expand Down
27 changes: 27 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
createSAdd,
createSCard,
createSMembers,
createSPop,
createSRem,
createSelect,
createSet,
Expand Down Expand Up @@ -677,6 +678,32 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createSismember(key, member));
}

/** Removes and returns one random member from the set value store at `key`.
* See https://redis.io/commands/spop/ for details.
* To pop multiple members, see `spopCount`.
*
* @param key - The key of the set.
*
* Command Response - the value of the popped member.
* If `key` does not exist, null will be returned.
*/
public spop(key: string): T {
return this.addAndReturn(createSPop(key));
}

/** Removes and returns up to `count` random members from the set value store at `key`, depending on the set's length.
* See https://redis.io/commands/spop/ for details.
*
* @param key - The key of the set.
* @param count - The count of the elements to pop from the set.
*
* Command Response - A list of popped elements will be returned depending on the set's length.
* If `key` does not exist, empty list will be returned.
*/
public spopCount(key: string, count: number): T {
return this.addAndReturn(createSPop(key, count));
}

/** Returns the number of keys in `keys` that exist in the database.
* See https://redis.io/commands/exists/ for details.
*
Expand Down
23 changes: 23 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1121,6 +1121,29 @@ export function runBaseTests<Context>(config: {
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`spop and spopCount test_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key = uuidv4();
const members = ["member1", "member2", "member3"];
expect(await client.sadd(key, members)).toEqual(3);

const result1 = await client.spop(key);
expect(members).toContain(result1);

const result2 = await client.spopCount(key, 2);
expect(members).toContain(result2?.[0]);
expect(members).toContain(result2?.[1]);
expect(result2).not.toContain(result1);

expect(await client.spop("nonExistingKey")).toEqual(null);
expect(await client.spopCount("nonExistingKey", 1)).toEqual([]);
}, protocol);
},
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`exists with existing keys, an non existing key_%p`,
async (protocol) => {
Expand Down
4 changes: 4 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ export async function transactionTest(
args.push(true);
baseTransaction.smembers(key7);
args.push(["bar"]);
baseTransaction.spop(key7);
args.push("bar");
baseTransaction.scard(key7);
args.push(0);
baseTransaction.zadd(key8, {
member1: 1,
member2: 2,
Expand Down

0 comments on commit 78cfa33

Please sign in to comment.