Skip to content

Commit

Permalink
Node: Add binary support to LINDEX LMOVE BLMOVE LINSERT LLEN (valkey-…
Browse files Browse the repository at this point in the history
…io#2166)

* add binary support to lindex lmove blmove linsert llen

---------

Signed-off-by: lior sventitzky <[email protected]>
  • Loading branch information
liorsve authored Aug 21, 2024
1 parent 56dead0 commit 2683edc
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 21 deletions.
40 changes: 28 additions & 12 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2189,7 +2189,7 @@ export class BaseClient {
* console.log(result); // Output: 3 - Indicates that there are 3 elements in the list.
* ```
*/
public async llen(key: string): Promise<number> {
public async llen(key: GlideString): Promise<number> {
return this.createWritePromise(createLLen(key));
}

Expand All @@ -2205,6 +2205,8 @@ export class BaseClient {
* @param destination - The key to the destination list.
* @param whereFrom - The {@link ListDirection} to remove the element from.
* @param whereTo - The {@link ListDirection} to add the element to.
* @param decoder - (Optional) {@link Decoder} type which defines how to handle the response.
* If not set, the {@link BaseClientConfiguration.defaultDecoder|default decoder} will be used.
* @returns The popped element, or `null` if `source` does not exist.
*
* @example
Expand All @@ -2223,13 +2225,15 @@ export class BaseClient {
* ```
*/
public async lmove(
source: string,
destination: string,
source: GlideString,
destination: GlideString,
whereFrom: ListDirection,
whereTo: ListDirection,
): Promise<string | null> {
decoder?: Decoder,
): Promise<GlideString | null> {
return this.createWritePromise(
createLMove(source, destination, whereFrom, whereTo),
{ decoder: decoder },
);
}

Expand All @@ -2249,6 +2253,8 @@ export class BaseClient {
* @param whereFrom - The {@link ListDirection} to remove the element from.
* @param whereTo - The {@link ListDirection} to add the element to.
* @param timeout - The number of seconds to wait for a blocking operation to complete. A value of `0` will block indefinitely.
* @param decoder - (Optional) {@link Decoder} type which defines how to handle the response.
* If not set, the {@link BaseClientConfiguration.defaultDecoder|default decoder} will be used.
* @returns The popped element, or `null` if `source` does not exist or if the operation timed-out.
*
* @example
Expand All @@ -2266,14 +2272,16 @@ export class BaseClient {
* ```
*/
public async blmove(
source: string,
destination: string,
source: GlideString,
destination: GlideString,
whereFrom: ListDirection,
whereTo: ListDirection,
timeout: number,
): Promise<string | null> {
decoder?: Decoder,
): Promise<GlideString | null> {
return this.createWritePromise(
createBLMove(source, destination, whereFrom, whereTo, timeout),
{ decoder: decoder },
);
}

Expand Down Expand Up @@ -5258,6 +5266,8 @@ export class BaseClient {
*
* @param key - The `key` of the list.
* @param index - The `index` of the element in the list to retrieve.
* @param decoder - (Optional) {@link Decoder} type which defines how to handle the response.
* If not set, the {@link BaseClientConfiguration.defaultDecoder|default decoder} will be used.
* @returns - The element at `index` in the list stored at `key`.
* If `index` is out of range or if `key` does not exist, null is returned.
*
Expand All @@ -5275,8 +5285,14 @@ export class BaseClient {
* console.log(result); // Output: 'value3' - Returns the last element in the list stored at 'my_list'.
* ```
*/
public async lindex(key: string, index: number): Promise<string | null> {
return this.createWritePromise(createLIndex(key, index));
public async lindex(
key: GlideString,
index: number,
decoder?: Decoder,
): Promise<GlideString | null> {
return this.createWritePromise(createLIndex(key, index), {
decoder: decoder,
});
}

/**
Expand All @@ -5300,10 +5316,10 @@ export class BaseClient {
* ```
*/
public async linsert(
key: string,
key: GlideString,
position: InsertPosition,
pivot: string,
element: string,
pivot: GlideString,
element: GlideString,
): Promise<number> {
return this.createWritePromise(
createLInsert(key, position, pivot, element),
Expand Down
18 changes: 9 additions & 9 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -884,7 +884,7 @@ export function createLRange(
/**
* @internal
*/
export function createLLen(key: string): command_request.Command {
export function createLLen(key: GlideString): command_request.Command {
return createCommand(RequestType.LLen, [key]);
}

Expand All @@ -906,8 +906,8 @@ export enum ListDirection {
* @internal
*/
export function createLMove(
source: string,
destination: string,
source: GlideString,
destination: GlideString,
whereFrom: ListDirection,
whereTo: ListDirection,
): command_request.Command {
Expand All @@ -923,8 +923,8 @@ export function createLMove(
* @internal
*/
export function createBLMove(
source: string,
destination: string,
source: GlideString,
destination: GlideString,
whereFrom: ListDirection,
whereTo: ListDirection,
timeout: number,
Expand Down Expand Up @@ -1857,7 +1857,7 @@ export function createStrlen(key: string): command_request.Command {
* @internal
*/
export function createLIndex(
key: string,
key: GlideString,
index: number,
): command_request.Command {
return createCommand(RequestType.LIndex, [key, index.toString()]);
Expand All @@ -1881,10 +1881,10 @@ export enum InsertPosition {
* @internal
*/
export function createLInsert(
key: string,
key: GlideString,
position: InsertPosition,
pivot: string,
element: string,
pivot: GlideString,
element: GlideString,
): command_request.Command {
return createCommand(RequestType.LInsert, [key, position, pivot, element]);
}
Expand Down
100 changes: 100 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2081,6 +2081,7 @@ export function runBaseTests(config: {
const valueList = ["value4", "value3", "value2", "value1"];
expect(await client.lpush(key1, valueList)).toEqual(4);
expect(await client.llen(key1)).toEqual(4);
expect(await client.llen(Buffer.from(key1))).toEqual(4);

expect(await client.llen("nonExistingKey")).toEqual(0);

Expand Down Expand Up @@ -2108,12 +2109,16 @@ export function runBaseTests(config: {

const key1 = "{key}-1" + uuidv4();
const key2 = "{key}-2" + uuidv4();
const key1Encoded = Buffer.from("{key}-1" + uuidv4());
const key2Encoded = Buffer.from("{key}-2" + uuidv4());
const lpushArgs1 = ["2", "1"];
const lpushArgs2 = ["4", "3"];

// Initialize the tests
expect(await client.lpush(key1, lpushArgs1)).toEqual(2);
expect(await client.lpush(key2, lpushArgs2)).toEqual(2);
expect(await client.lpush(key1Encoded, lpushArgs1)).toEqual(2);
expect(await client.lpush(key2Encoded, lpushArgs2)).toEqual(2);

// Move from LEFT to LEFT
expect(
Expand Down Expand Up @@ -2166,6 +2171,27 @@ export function runBaseTests(config: {
expect(await client.lrange(key2, 0, -1)).toEqual(["1", "3"]);
expect(await client.lrange(key1, 0, -1)).toEqual(["2", "4"]);

// Move from RIGHT to LEFT with encoded return value
expect(
await client.lmove(
key1,
key2,
ListDirection.RIGHT,
ListDirection.LEFT,
Decoder.Bytes,
),
).toEqual(Buffer.from("4"));

// Move from RIGHT to LEFT with encoded list keys
expect(
await client.lmove(
key1Encoded,
key2Encoded,
ListDirection.RIGHT,
ListDirection.LEFT,
),
).toEqual("2");

// Non-existing source key
expect(
await client.lmove(
Expand Down Expand Up @@ -2212,12 +2238,16 @@ export function runBaseTests(config: {

const key1 = "{key}-1" + uuidv4();
const key2 = "{key}-2" + uuidv4();
const key1Encoded = Buffer.from("{key}-1" + uuidv4());
const key2Encoded = Buffer.from("{key}-2" + uuidv4());
const lpushArgs1 = ["2", "1"];
const lpushArgs2 = ["4", "3"];

// Initialize the tests
expect(await client.lpush(key1, lpushArgs1)).toEqual(2);
expect(await client.lpush(key2, lpushArgs2)).toEqual(2);
expect(await client.lpush(key1Encoded, lpushArgs1)).toEqual(2);
expect(await client.lpush(key2Encoded, lpushArgs2)).toEqual(2);

// Move from LEFT to LEFT with blocking
expect(
Expand Down Expand Up @@ -2281,6 +2311,29 @@ export function runBaseTests(config: {
expect(await client.lrange(key2, 0, -1)).toEqual(["1", "3"]);
expect(await client.lrange(key1, 0, -1)).toEqual(["2", "4"]);

// Move from RIGHT to LEFT with blocking and encoded return value
expect(
await client.blmove(
key1,
key2,
ListDirection.RIGHT,
ListDirection.LEFT,
0.1,
Decoder.Bytes,
),
).toEqual(Buffer.from("4"));

// Move from RIGHT to LEFT with encoded list keys
expect(
await client.blmove(
key1Encoded,
key2Encoded,
ListDirection.RIGHT,
ListDirection.LEFT,
0.1,
),
).toEqual("2");

// Non-existing source key with blocking
expect(
await client.blmove(
Expand Down Expand Up @@ -5291,6 +5344,7 @@ export function runBaseTests(config: {
async (protocol) => {
await runTest(async (client: BaseClient) => {
const listName = uuidv4();
const encodedListName = Buffer.from(uuidv4());
const listKey1Value = uuidv4();
const listKey2Value = uuidv4();
expect(
Expand All @@ -5299,10 +5353,25 @@ export function runBaseTests(config: {
listKey2Value,
]),
).toEqual(2);
expect(
await client.lpush(encodedListName, [
Buffer.from(listKey1Value),
Buffer.from(listKey2Value),
]),
).toEqual(2);
expect(await client.lindex(listName, 0)).toEqual(listKey2Value);
expect(await client.lindex(listName, 1)).toEqual(listKey1Value);
expect(await client.lindex("notExsitingList", 1)).toEqual(null);
expect(await client.lindex(listName, 3)).toEqual(null);
expect(await client.lindex(listName, 0, Decoder.Bytes)).toEqual(
Buffer.from(listKey2Value),
);
expect(await client.lindex(listName, 1, Decoder.Bytes)).toEqual(
Buffer.from(listKey1Value),
);
expect(await client.lindex(encodedListName, 0)).toEqual(
listKey2Value,
);
}, protocol);
},
config.timeout,
Expand All @@ -5313,6 +5382,8 @@ export function runBaseTests(config: {
async (protocol) => {
await runTest(async (client: BaseClient) => {
const key1 = uuidv4();
const key2 = uuidv4();
const key2Encoded = Buffer.from(key2);
const stringKey = uuidv4();
const nonExistingKey = uuidv4();

Expand Down Expand Up @@ -5361,6 +5432,35 @@ export function runBaseTests(config: {
),
).toEqual(0);

// key, pivot and element as buffers
expect(await client.lpush(key2, ["4", "3", "2", "1"])).toEqual(
4,
);
expect(
await client.linsert(
key2Encoded,
InsertPosition.Before,
Buffer.from("2"),
Buffer.from("1.5"),
),
).toEqual(5);
expect(
await client.linsert(
key2Encoded,
InsertPosition.After,
Buffer.from("3"),
Buffer.from("3.5"),
),
).toEqual(6);
expect(await client.lrange(key2Encoded, 0, -1)).toEqual([
"1",
"1.5",
"2",
"3",
"3.5",
"4",
]);

// key exists, but it is not a list
expect(await client.set(stringKey, "value")).toEqual("OK");
await expect(
Expand Down

0 comments on commit 2683edc

Please sign in to comment.