Skip to content

Commit

Permalink
Node: add SETBIT command (valkey-io#1978)
Browse files Browse the repository at this point in the history
* Node: add SETBIT command

Signed-off-by: aaron-congo <[email protected]>
  • Loading branch information
aaron-congo authored Jul 19, 2024
1 parent 4533298 commit 5bef4df
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#### Changes
* Node: Added GETDEL command ([#1968](https://github.com/valkey-io/valkey-glide/pull/1968))
* Node: Added SETBIT command ([#1978](https://github.com/valkey-io/valkey-glide/pull/1978))
* Node: Added LPUSHX and RPUSHX command([#1959](https://github.com/valkey-io/valkey-glide/pull/1959))
* Node: Added LSET command ([#1952](https://github.com/valkey-io/valkey-glide/pull/1952))
* Node: Added SDIFFSTORE command ([#1931](https://github.com/valkey-io/valkey-glide/pull/1931))
Expand Down
24 changes: 24 additions & 0 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import {
createSCard,
createSDiff,
createSDiffStore,
createSetBit,
createSInter,
createSInterCard,
createSInterStore,
Expand Down Expand Up @@ -962,6 +963,29 @@ export class BaseClient {
return this.createWritePromise(createDecrBy(key, amount));
}

/**
* Sets or clears the bit at `offset` in the string value stored at `key`. The `offset` is a zero-based index, with
* `0` being the first element of the list, `1` being the next element, and so on. The `offset` must be less than
* `2^32` and greater than or equal to `0`. If a key is non-existent then the bit at `offset` is set to `value` and
* the preceding bits are set to `0`.
*
* See https://valkey.io/commands/setbit/ for more details.
*
* @param key - The key of the string.
* @param offset - The index of the bit to be set.
* @param value - The bit value to set at `offset`. The value must be `0` or `1`.
* @returns The bit value that was previously stored at `offset`.
*
* @example
* ```typescript
* const result = await client.setbit("key", 1, 1);
* console.log(result); // Output: 0 - The second bit value was 0 before setting to 1.
* ```
*/
public setbit(key: string, offset: number, value: number): Promise<number> {
return this.createWritePromise(createSetBit(key, offset, value));
}

/** Retrieve the value associated with `field` in the hash stored at `key`.
* See https://valkey.io/commands/hget/ for details.
*
Expand Down
15 changes: 15 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,21 @@ export function createDecrBy(
return createCommand(RequestType.DecrBy, [key, amount.toString()]);
}

/**
* @internal
*/
export function createSetBit(
key: string,
offset: number,
value: number,
): command_request.Command {
return createCommand(RequestType.SetBit, [
key,
offset.toString(),
value.toString(),
]);
}

/**
* @internal
*/
Expand Down
19 changes: 19 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ import {
createSCard,
createSDiff,
createSDiffStore,
createSetBit,
createSInter,
createSInterCard,
createSInterStore,
Expand Down Expand Up @@ -375,6 +376,24 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createDecrBy(key, amount));
}

/**
* Sets or clears the bit at `offset` in the string value stored at `key`. The `offset` is a zero-based index, with
* `0` being the first element of the list, `1` being the next element, and so on. The `offset` must be less than
* `2^32` and greater than or equal to `0`. If a key is non-existent then the bit at `offset` is set to `value` and
* the preceding bits are set to `0`.
*
* See https://valkey.io/commands/setbit/ for more details.
*
* @param key - The key of the string.
* @param offset - The index of the bit to be set.
* @param value - The bit value to set at `offset`. The value must be `0` or `1`.
*
* Command Response - The bit value that was previously stored at `offset`.
*/
public setbit(key: string, offset: number, value: number): T {
return this.addAndReturn(createSetBit(key, offset, value));
}

/** Reads the configuration parameters of a running Redis server.
* See https://valkey.io/commands/config-get/ for details.
*
Expand Down
30 changes: 30 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,36 @@ export function runBaseTests<Context>(config: {
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`setbit test_%p`,
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key = `{key}-${uuidv4()}`;
const stringKey = `{key}-${uuidv4()}`;

expect(await client.setbit(key, 1, 1)).toEqual(0);
expect(await client.setbit(key, 1, 0)).toEqual(1);

// invalid argument - offset can't be negative
await expect(client.setbit(key, -1, 1)).rejects.toThrow(
RequestError,
);

// invalid argument - "value" arg must be 0 or 1
await expect(client.setbit(key, 0, 2)).rejects.toThrow(
RequestError,
);

// key exists, but it is not a string
expect(await client.sadd(stringKey, ["foo"])).toEqual(1);
await expect(client.setbit(stringKey, 0, 0)).rejects.toThrow(
RequestError,
);
}, protocol);
},
config.timeout,
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
`config get and config set with timeout parameter_%p`,
async (protocol) => {
Expand Down
5 changes: 5 additions & 0 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ export async function transactionTest(
const key14 = "{key}" + uuidv4(); // sorted set
const key15 = "{key}" + uuidv4(); // list
const key16 = "{key}" + uuidv4(); // list
const key17 = "{key}" + uuidv4(); // bitmap
const field = uuidv4();
const value = uuidv4();
const args: ReturnType[] = [];
Expand Down Expand Up @@ -604,6 +605,10 @@ export async function transactionTest(
args.push([key6, field + "3"]);
baseTransaction.blpop([key6], 0.1);
args.push([key6, field + "1"]);

baseTransaction.setbit(key17, 1, 1);
args.push(0);

baseTransaction.pfadd(key11, ["a", "b", "c"]);
args.push(1);
baseTransaction.pfcount([key11]);
Expand Down

0 comments on commit 5bef4df

Please sign in to comment.