Skip to content

Commit

Permalink
Add command HStrlen (valkey-io#2020)
Browse files Browse the repository at this point in the history
* Add command HStrlen
  • Loading branch information
tjzhang-BQ authored Jul 26, 2024
1 parent cc1c2e6 commit 0672ea3
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@
* Node: Added ZRevRank command ([#1977](https://github.com/valkey-io/valkey-glide/pull/1977))
* Node: Added GeoDist command ([#1988](https://github.com/valkey-io/valkey-glide/pull/1988))
* Node: Added GeoHash command ([#1997](https://github.com/valkey-io/valkey-glide/pull/1997))
* Node: Added HStrlen command ([#2020](https://github.com/valkey-io/valkey-glide/pull/2020))

#### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/valkey-io/valkey-glide/pull/1494))
Expand Down
21 changes: 21 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ import {
createHMGet,
createHSet,
createHSetNX,
createHStrlen,
createHVals,
createIncr,
createIncrBy,
Expand Down Expand Up @@ -1393,6 +1394,26 @@ export class BaseClient {
return this.createWritePromise(createHVals(key));
}

/**
* Returns the string length of the value associated with `field` in the hash stored at `key`.
*
* See https://valkey.io/commands/hstrlen/ for details.
*
* @param key - The key of the hash.
* @param field - The field in the hash.
* @returns The string length or `0` if `field` or `key` does not exist.
*
* @example
* ```typescript
* await client.hset("my_hash", {"field": "value"});
* const result = await client.hstrlen("my_hash", "field");
* console.log(result); // Output: 5
* ```
*/
public hstrlen(key: string, field: string): Promise<number> {
return this.createWritePromise(createHStrlen(key, field));
}

/** Inserts all the specified values at the head of the list stored at `key`.
* `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element.
* If `key` does not exist, it is created as empty list before performing the push operations.
Expand Down
10 changes: 10 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2249,3 +2249,13 @@ export function createZIncrBy(
member,
]);
}

/**
* @internal
*/
export function createHStrlen(
key: string,
field: string,
): command_request.Command {
return createCommand(RequestType.HStrlen, [key, field]);
}
15 changes: 15 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ import {
createHMGet,
createHSet,
createHSetNX,
createHStrlen,
createHVals,
createIncr,
createIncrBy,
Expand Down Expand Up @@ -680,6 +681,20 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createHVals(key));
}

/**
* Returns the string length of the value associated with `field` in the hash stored at `key`.
*
* See https://valkey.io/commands/hstrlen/ for details.
*
* @param key - The key of the hash.
* @param field - The field in the hash.
*
* Command Response - The string length or `0` if `field` or `key` does not exist.
*/
public hstrlen(key: string, field: string): T {
return this.addAndReturn(createHStrlen(key, field));
}

/** Inserts all the specified values at the head of the list stored at `key`.
* `elements` are inserted one after the other to the head of the list, from the leftmost element to the rightmost element.
* If `key` does not exist, it is created as empty list before performing the push operations.
Expand Down
27 changes: 27 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,33 @@ export function runBaseTests<Context>(config: {
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`hstrlen test_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key1 = uuidv4();
const key2 = uuidv4();
const field = uuidv4();

expect(await client.hset(key1, { field: "value" })).toBe(1);
expect(await client.hstrlen(key1, "field")).toBe(5);

// missing value
expect(await client.hstrlen(key1, "nonExistingField")).toBe(0);

// missing key
expect(await client.hstrlen(key2, "field")).toBe(0);

// key exists but holds non hash type value
checkSimple(await client.set(key2, "value")).toEqual("OK");
await expect(client.hstrlen(key2, field)).rejects.toThrow(
RequestError,
);
}, protocol);
},
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`lpush, lpop and lrange with existing and non existing key_%p`,
async (protocol) => {
Expand Down
2 changes: 2 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,8 @@ export async function transactionTest(
responseData.push(["del([key1])", 1]);
baseTransaction.hset(key4, { [field]: value });
responseData.push(["hset(key4, { [field]: value })", 1]);
baseTransaction.hstrlen(key4, field);
responseData.push(["hstrlen(key4, field)", value.length]);
baseTransaction.hlen(key4);
responseData.push(["hlen(key4)", 1]);
baseTransaction.hsetnx(key4, field, value);
Expand Down

0 comments on commit 0672ea3

Please sign in to comment.