Skip to content

Commit

Permalink
hset parameter updated to HashDataType (valkey-io#2209)
Browse files Browse the repository at this point in the history
* hset parameter updated to HashDataType

Signed-off-by: Prateek Kumar <[email protected]>
  • Loading branch information
prateek-kumar-improving authored Aug 30, 2024
1 parent 8d482be commit 7e8525b
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 31 deletions.
50 changes: 44 additions & 6 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,28 @@ export type DecoderOption = {
decoder?: Decoder;
};

/**
* This function converts an input from HashDataType or Record types to HashDataType.
*
* @param fieldsAndValues - field names and their values.
* @returns HashDataType array containing field names and their values.
*/
export function convertFieldsAndValuesForHset(
fieldsAndValues: HashDataType | Record<string, GlideString>,
): HashDataType {
let finalFieldAndValues = [];

if (!Array.isArray(fieldsAndValues)) {
finalFieldAndValues = Object.entries(fieldsAndValues).map((e) => {
return { field: e[0], value: e[1] };
});
} else {
finalFieldAndValues = fieldsAndValues;
}

return finalFieldAndValues;
}

/**
* Our purpose in creating PointerResponse type is to mark when response is of number/long pointer response type.
* Consequently, when the response is returned, we can check whether it is instanceof the PointerResponse type and pass it to the Rust core function with the proper parameters.
Expand All @@ -319,6 +341,17 @@ class PointerResponse {
}
}

/**
* Data type which represents how data are returned from hashes or insterted there.
* Similar to `Record<GlideString, GlideString>` - see {@link GlideRecord}.
*/
export type HashDataType = {
/** The hash element name. */
field: GlideString;
/** The hash element value. */
value: GlideString;
}[];

/** Represents the credentials for connecting to a server. */
export type RedisCredentials = {
/**
Expand Down Expand Up @@ -1650,22 +1683,27 @@ export class BaseClient {
* @see {@link https://valkey.io/commands/hset/|valkey.io} for details.
*
* @param key - The key of the hash.
* @param fieldValueMap - A field-value map consisting of fields and their corresponding values
* to be set in the hash stored at the specified key.
* @param fieldsAndValues - A list of field names and their values.
* @returns The number of fields that were added.
*
* @example
* ```typescript
* // Example usage of the hset method
* const result = await client.hset("my_hash", {"field": "value", "field2": "value2"});
* // Example usage of the hset method using HashDataType as input type
* const result = await client.hset("my_hash", [{"field": "field1", "value": "value1"}, {"field": "field2", "value": "value2"}]);
* console.log(result); // Output: 2 - Indicates that 2 fields were successfully set in the hash "my_hash".
*
* // Example usage of the hset method using Record<string, GlideString> as input
* const result = await client.hset("my_hash", {"field1": "value", "field2": "value2"});
* console.log(result); // Output: 2 - Indicates that 2 fields were successfully set in the hash "my_hash".
* ```
*/
public async hset(
key: GlideString,
fieldValueMap: Record<string, string>,
fieldsAndValues: HashDataType | Record<string, GlideString>,
): Promise<number> {
return this.createWritePromise(createHSet(key, fieldValueMap));
return this.createWritePromise(
createHSet(key, convertFieldsAndValuesForHset(fieldsAndValues)),
);
}

/**
Expand Down
13 changes: 10 additions & 3 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { createLeakedStringVec, MAX_REQUEST_ARGS_LEN } from "glide-rs";
import Long from "long";

/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
import { BaseClient } from "src/BaseClient";
import { BaseClient, HashDataType } from "src/BaseClient";
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
import { GlideClient } from "src/GlideClient";
/* eslint-disable-next-line @typescript-eslint/no-unused-vars */
Expand Down Expand Up @@ -413,11 +413,18 @@ export function createHGet(
*/
export function createHSet(
key: GlideString,
fieldValueMap: Record<string, string>,
fieldValueList: HashDataType,
): command_request.Command {
return createCommand(
RequestType.HSet,
[key].concat(Object.entries(fieldValueMap).flat()),
[key].concat(
fieldValueList
.map((fieldValueObject) => [
fieldValueObject.field,
fieldValueObject.value,
])
.flat(),
),
);
}

Expand Down
14 changes: 10 additions & 4 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import {
BaseClient, // eslint-disable-line @typescript-eslint/no-unused-vars
GlideString,
ReadFrom, // eslint-disable-line @typescript-eslint/no-unused-vars
HashDataType,
convertFieldsAndValuesForHset,
} from "./BaseClient";

import {
Expand Down Expand Up @@ -804,13 +805,18 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
* @see {@link https://valkey.io/commands/hset/|valkey.io} for details.
*
* @param key - The key of the hash.
* @param fieldValueMap - A field-value map consisting of fields and their corresponding values
* @param fieldValueList - A list of field names and their values.
* to be set in the hash stored at the specified key.
*
* Command Response - The number of fields that were added.
*/
public hset(key: GlideString, fieldValueMap: Record<string, string>): T {
return this.addAndReturn(createHSet(key, fieldValueMap));
public hset(
key: GlideString,
fieldsAndValues: HashDataType | Record<string, GlideString>,
): T {
return this.addAndReturn(
createHSet(key, convertFieldsAndValuesForHset(fieldsAndValues)),
);
}

/**
Expand Down
20 changes: 14 additions & 6 deletions node/tests/GlideClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { v4 as uuidv4 } from "uuid";
import {
Decoder,
GlideClient,
HashDataType,
ProtocolVersion,
RequestError,
Transaction,
Expand Down Expand Up @@ -1166,11 +1167,12 @@ describe("GlideClient", () => {
const ages = ["30", "25", "35", "20", "40"];

for (let i = 0; i < ages.length; i++) {
const fieldValueList: HashDataType = [
{ field: "name", value: names[i] },
{ field: "age", value: ages[i] },
];
expect(
await client.hset(setPrefix + (i + 1), {
name: names[i],
age: ages[i],
}),
await client.hset(setPrefix + (i + 1), fieldValueList),
).toEqual(2);
}

Expand Down Expand Up @@ -1331,8 +1333,14 @@ describe("GlideClient", () => {

// transaction test
const transaction = new Transaction()
.hset(hashPrefix + 1, { name: "Alice", age: "30" })
.hset(hashPrefix + 2, { name: "Bob", age: "25" })
.hset(hashPrefix + 1, [
{ field: "name", value: "Alice" },
{ field: "age", value: "30" },
])
.hset(hashPrefix + 2, {
name: "Bob",
age: "25",
})
.del([list])
.lpush(list, ["2", "1"])
.sort(list, {
Expand Down
35 changes: 24 additions & 11 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
// represents a running server instance. See first 2 test cases as examples.

import { expect, it } from "@jest/globals";
import { HashDataType } from "src/BaseClient";
import { v4 as uuidv4 } from "uuid";
import {
BaseClientConfiguration,
Expand Down Expand Up @@ -1332,13 +1333,20 @@ export function runBaseTests(config: {
const field1 = uuidv4();
const field2 = uuidv4();
const value = uuidv4();
const fieldValueMap = {
[field1]: value,
[field2]: value,
};
const fieldValueList: HashDataType = [
{
field: Buffer.from(field1),
value: Buffer.from(value),
},
{
field: Buffer.from(field2),
value: Buffer.from(value),
},
];

const valueEncoded = Buffer.from(value);

expect(await client.hset(key, fieldValueMap)).toEqual(2);
expect(await client.hset(key, fieldValueList)).toEqual(2);
expect(
await client.hget(Buffer.from(key), Buffer.from(field1)),
).toEqual(value);
Expand Down Expand Up @@ -1864,12 +1872,18 @@ export function runBaseTests(config: {
const key1 = uuidv4();
const field1 = uuidv4();
const field2 = uuidv4();
const fieldValueMap = {
[field1]: "value1",
[field2]: "value2",
};
const fieldValueList = [
{
field: field1,
value: "value1",
},
{
field: field2,
value: "value2",
},
];

expect(await client.hset(key1, fieldValueMap)).toEqual(2);
expect(await client.hset(key1, fieldValueList)).toEqual(2);
expect(await client.hlen(key1)).toEqual(2);
expect(await client.hdel(key1, [field1])).toEqual(1);
expect(await client.hlen(Buffer.from(key1))).toEqual(1);
Expand All @@ -1891,7 +1905,6 @@ export function runBaseTests(config: {
[field1]: "value1",
[field2]: "value2",
};

const value1Encoded = Buffer.from("value1");
const value2Encoded = Buffer.from("value2");

Expand Down
2 changes: 1 addition & 1 deletion node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ export async function transactionTest(
responseData.push(["append(key1, value)", 3]);
baseTransaction.del([key1]);
responseData.push(["del([key1])", 1]);
baseTransaction.hset(key4, { [field]: value });
baseTransaction.hset(key4, [{ field, value }]);
responseData.push(["hset(key4, { [field]: value })", 1]);
baseTransaction.hscan(key4, "0");
responseData.push(['hscan(key4, "0")', ["0", [field, value]]]);
Expand Down

0 comments on commit 7e8525b

Please sign in to comment.