Skip to content

Commit

Permalink
added hincrBy and hincrByFloat in node
Browse files Browse the repository at this point in the history
  • Loading branch information
Adan committed Oct 11, 2023
1 parent cb722c2 commit 8798b86
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 0 deletions.
43 changes: 43 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import {
createHExists,
createHGet,
createHGetAll,
createHIncrBy,
createHIncrByFloat,
createHMGet,
createHSet,
createIncr,
Expand Down Expand Up @@ -471,6 +473,47 @@ export class BaseClient {
return this.createWritePromise(createHGetAll(key));
}

/** Increments the number stored at `field` in the hash stored at `key` by increment.
* By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented.
* If `field` or `key` does not exist, it is set to 0 before performing the operation.
* See https://redis.io/commands/hincrby/ for details.
*
* @param key - The key of the hash.
* @param amount - The amount to increment.
* @param field - The field in the hash stored at `key` to increment its value.
* @returns the value of `field` in the hash stored at `key` after the increment.
* An error will be returned if `key` holds a value of an incorrect type (not a string)
* or if it contains a string that cannot be represented as an integer.
*/
public hincrBy(
key: string,
field: string,
amount: number
): Promise<number> {
return this.createWritePromise(createHIncrBy(key, field, amount));
}

/** Increment the string representing a floating point number stored at `field` in the hash stored at `key` by increment.
* By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented.
* If `field` or `key` does not exist, it is set to 0 before performing the operation.
* See https://redis.io/commands/hincrbyfloat/ for details.
*
* @param key - The key of the hash.
* @param amount - The amount to increment.
* @param field - The field in the hash stored at `key` to increment its value.
* @returns the value of `field` in the hash stored at `key` after the increment as string.
* An error is returned if `key` contains a value of the wrong type
* or the current field content is not parsable as a double precision floating point number.
*
*/
public hincrByFloat(
key: string,
field: string,
amount: number
): Promise<string> {
return this.createWritePromise(createHIncrByFloat(key, field, amount));
}

private readonly MAP_READ_FROM_REPLICA_STRATEGY: Record<
ReadFromReplicaStrategy,
connection_request.ReadFromReplicaStrategy
Expand Down
24 changes: 24 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,3 +340,27 @@ export function createHGetAll(key: string): redis_request.Command {
export function createCustomCommand(commandName: string, args: string[]) {
return createCommand(RequestType.CustomCommand, [commandName, ...args]);
}

export function createHIncrBy(
key: string,
field: string,
amount: number
): redis_request.Command {
return createCommand(RequestType.HashIncrBy, [
key,
field,
amount.toString(),
]);
}

export function createHIncrByFloat(
key: string,
field: string,
amount: number
): redis_request.Command {
return createCommand(RequestType.HashIncrByFloat, [
key,
field,
amount.toString(),
]);
}
37 changes: 37 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
createHExists,
createHGet,
createHGetAll,
createHIncrBy,
createHIncrByFloat,
createHMGet,
createHSet,
createIncr,
Expand Down Expand Up @@ -339,6 +341,41 @@ export class BaseTransaction {
this.commands.push(createHGetAll(key));
}

/** Increments the number stored at `field` in the hash stored at `key` by `increment`.
* By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented.
* If `field` or `key` does not exist, it is set to 0 before performing the operation.
* See https://redis.io/commands/hincrby/ for details.
*
* @param key - The key of the hash.
* @param amount - The amount to increment.
* @param field - The field in the hash stored at `key` to increment its value.
*
* Command Response - the value of `field` in the hash stored at `key` after the increment.
* An error will be returned if `key` holds a value of an incorrect type (not a string)
* or if it contains a string that cannot be represented as an integer.
*/
public hincrBy(key: string, field: string, amount: number) {
this.commands.push(createHIncrBy(key, field, amount));
}

/** Increment the string representing a floating point number stored at `field` in the hash stored at `key` by `increment`.
* By using a negative increment value, the value stored at `field` in the hash stored at `key` is decremented.
* If `field` or `key` does not exist, it is set to 0 before performing the operation.
* See https://redis.io/commands/hincrbyfloat/ for details.
*
* @param key - The key of the hash.
* @param amount - The amount to increment.
* @param field - The field in the hash stored at `key` to increment its value.
*
* Command Response - the value of `field` in the hash stored at `key` after the increment as string.
* An error is returned if `key` contains a value of the wrong type
* or the current field content is not parsable as a double precision floating point number.
*
*/
public hincrByFloat(key: string, field: string, amount: number) {
this.commands.push(createHIncrByFloat(key, field, amount));
}

/** 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
84 changes: 84 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ type BaseClient = {
hmget: (key: string, fields: string[]) => Promise<(string | null)[]>;
hexists: (key: string, field: string) => Promise<number>;
hgetall: (key: string) => Promise<string[]>;
hincrBy: (key: string, field: string, amount: number) => Promise<number>;
hincrByFloat: (
key: string,
field: string,
amount: number
) => Promise<string>;
customCommand: (commandName: string, args: string[]) => Promise<ReturnType>;
};

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

it(
"hincrBy and hincrByFloat with existing key and field",
async () => {
await runTest(async (client: BaseClient) => {
const key = uuidv4();
const field = uuidv4();
const fieldValueMap = {
[field]: "10",
};
expect(await client.hset(key, fieldValueMap)).toEqual(1);
expect(await client.hincrBy(key, field, 1)).toEqual(11);
expect(await client.hincrBy(key, field, 4)).toEqual(15);
expect(await client.hincrByFloat(key, field, 1.5)).toEqual(
"16.5"
);
});
},
config.timeout
);

it(
"hincrBy and hincrByFloat with non existing key and non existing field",
async () => {
await runTest(async (client: BaseClient) => {
const key1 = uuidv4();
const key2 = uuidv4();
const field = uuidv4();
const fieldValueMap = {
[field]: "10",
};
expect(
await client.hincrBy("nonExistingKey", field, 1)
).toEqual(1);
expect(await client.hset(key1, fieldValueMap)).toEqual(1);
expect(
await client.hincrBy(key1, "nonExistingField", 2)
).toEqual(2);
expect(await client.hset(key2, fieldValueMap)).toEqual(1);
expect(
await client.hincrByFloat(key2, "nonExistingField", -0.5)
).toEqual("-0.5");
});
},
config.timeout
);

it(
"hincrBy and hincrByFloat with a field that contains a value of string that can not be represented as as integer or float",
async () => {
await runTest(async (client: BaseClient) => {
const key = uuidv4();
const field = uuidv4();
const fieldValueMap = {
[field]: "foo",
};
expect(await client.hset(key, fieldValueMap)).toEqual(1);
try {
expect(await client.hincrBy(key, field, 2)).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"hash value is not an integer"
);
}

try {
expect(
await client.hincrByFloat(key, field, 1.5)
).toThrow();
} catch (e) {
expect((e as Error).message).toMatch(
"hash value is not a float"
);
}
});
},
config.timeout
);
}

export function runCommonTests<Context>(config: {
Expand Down

0 comments on commit 8798b86

Please sign in to comment.