Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node: Add invokeScript for cluster client. #2284

Merged
merged 3 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#### Changes
* Node: Added `invokeScript` API with routing for cluster client ([#2284](https://github.com/valkey-io/valkey-glide/pull/2284))
* Python: Replace instances of Redis with Valkey ([#2266](https://github.com/valkey-io/valkey-glide/pull/2266))
* Java: Replace instances of Redis with Valkey ([#2268](https://github.com/valkey-io/valkey-glide/pull/2268))
* Node: Replace instances of Redis with Valkey ([#2260](https://github.com/valkey-io/valkey-glide/pull/2260))
Expand Down
2 changes: 0 additions & 2 deletions node/npm/glide/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ function initialize() {
StreamReadOptions,
StreamClaimOptions,
StreamPendingOptions,
ScriptOptions,
ClosingError,
ConfigurationError,
ExecAbortError,
Expand Down Expand Up @@ -284,7 +283,6 @@ function initialize() {
StreamReadGroupOptions,
StreamReadOptions,
StreamPendingOptions,
ScriptOptions,
ClosingError,
ConfigurationError,
ExecAbortError,
Expand Down
42 changes: 11 additions & 31 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -565,17 +565,6 @@ export interface BaseClientConfiguration {
defaultDecoder?: Decoder;
}

export interface ScriptOptions {
/**
* The keys that are used in the script.
*/
keys?: GlideString[];
/**
* The arguments for the script.
*/
args?: GlideString[];
}

/**
* Enum of Valkey data types
* `STRING`
Expand Down Expand Up @@ -3695,9 +3684,13 @@ export class BaseClient {
* it will be loaded automatically using the `SCRIPT LOAD` command. After that, it will be invoked using the `EVALSHA` command.
*
* @see {@link https://valkey.io/commands/script-load/|SCRIPT LOAD} and {@link https://valkey.io/commands/evalsha/|EVALSHA} on valkey.io for details.
* @remarks When in cluster mode, all `keys` must map to the same hash slot.
*
* @param script - The Lua script to execute.
* @param options - (Optional) See {@link ScriptOptions} and {@link DecoderOption}.
* @param options - (Optional) Additional parameters:
* - (Optional) `keys` : the keys that are used in the script.
* - (Optional) `args`: the arguments for the script.
* - (Optional) `decoder`: see {@link DecoderOption}.
* @returns A value that depends on the script that was executed.
*
* @example
Expand All @@ -3713,28 +3706,15 @@ export class BaseClient {
*/
public async invokeScript(
script: Script,
options?: ScriptOptions & DecoderOption,
options?: {
keys?: GlideString[];
args?: GlideString[];
} & DecoderOption,
): Promise<GlideReturnType> {
const scriptInvocation = command_request.ScriptInvocation.create({
hash: script.getHash(),
keys: options?.keys?.map((item) => {
if (typeof item === "string") {
// Convert the string to a Buffer
return Buffer.from(item);
} else {
// If it's already a Buffer, just return it
return item;
}
}),
args: options?.args?.map((item) => {
if (typeof item === "string") {
// Convert the string to a Buffer
return Buffer.from(item);
} else {
// If it's already a Buffer, just return it
return item;
}
}),
keys: options?.keys?.map(Buffer.from),
args: options?.args?.map(Buffer.from),
});
return this.createWritePromise(scriptInvocation, options);
}
Expand Down
6 changes: 3 additions & 3 deletions node/src/GlideClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ export class GlideClient extends BaseClient {
}

/**
* Check existence of scripts in the script cache by their SHA1 digest.
* Checks existence of scripts in the script cache by their SHA1 digest.
*
* @see {@link https://valkey.io/commands/script-exists/|valkey.io} for more details.
*
Expand All @@ -941,7 +941,7 @@ export class GlideClient extends BaseClient {
}

/**
* Flush the Lua scripts cache.
* Flushes the Lua scripts cache.
*
* @see {@link https://valkey.io/commands/script-flush/|valkey.io} for more details.
*
Expand All @@ -961,7 +961,7 @@ export class GlideClient extends BaseClient {
}

/**
* Kill the currently executing Lua script, assuming no write operation was yet performed by the script.
* Kills the currently executing Lua script, assuming no write operation was yet performed by the script.
*
* @see {@link https://valkey.io/commands/script-kill/|valkey.io} for more details.
*
Expand Down
46 changes: 43 additions & 3 deletions node/src/GlideClusterClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/

import { ClusterScanCursor } from "glide-rs";
import { Script } from "index";
import * as net from "net";
import {
BaseClient,
Expand Down Expand Up @@ -1442,7 +1443,46 @@ export class GlideClusterClient extends BaseClient {
}

/**
* Check existence of scripts in the script cache by their SHA1 digest.
* Invokes a Lua script with arguments.
* This method simplifies the process of invoking scripts on a Valkey server by using an object that represents a Lua script.
* The script loading, argument preparation, and execution will all be handled internally. If the script has not already been loaded,
* it will be loaded automatically using the `SCRIPT LOAD` command. After that, it will be invoked using the `EVALSHA` command.
*
* The command will be routed to a random node, unless `route` is provided.
*
* @see {@link https://valkey.io/commands/script-load/|SCRIPT LOAD} and {@link https://valkey.io/commands/evalsha/|EVALSHA} on valkey.io for details.
*
* @param script - The Lua script to execute.
* @param options - (Optional) Additional parameters:
* - (Optional) `args`: the arguments for the script.
* - (Optional) `decoder`: see {@link DecoderOption}.
* - (Optional) `route`: see {@link RouteOption}.
* @returns A value that depends on the script that was executed.
*
* @example
* ```typescript
* const luaScript = new Script("return { ARGV[1] }");
* const result = await invokeScript(luaScript, { args: ["bar"] });
* console.log(result); // Output: ['bar']
* ```
*/
public async invokeScriptWithRoute(
script: Script,
options?: { args?: GlideString[] } & DecoderOption & RouteOption,
): Promise<ClusterResponse<GlideReturnType>> {
const scriptInvocation = command_request.ScriptInvocation.create({
hash: script.getHash(),
keys: [],
args: options?.args?.map(Buffer.from),
});
return this.createWritePromise<ClusterGlideRecord<GlideReturnType>>(
scriptInvocation,
options,
).then((res) => convertClusterGlideRecord(res, true, options?.route));
}

/**
* Checks existence of scripts in the script cache by their SHA1 digest.
*
* @see {@link https://valkey.io/commands/script-exists/|valkey.io} for more details.
*
Expand All @@ -1464,7 +1504,7 @@ export class GlideClusterClient extends BaseClient {
}

/**
* Flush the Lua scripts cache.
* Flushes the Lua scripts cache.
*
* @see {@link https://valkey.io/commands/script-flush/|valkey.io} for more details.
*
Expand All @@ -1491,7 +1531,7 @@ export class GlideClusterClient extends BaseClient {
}

/**
* Kill the currently executing Lua script, assuming no write operation was yet performed by the script.
* Kills the currently executing Lua script, assuming no write operation was yet performed by the script.
*
* @see {@link https://valkey.io/commands/script-kill/|valkey.io} for more details.
* @remarks The command is routed to all nodes, and aggregates the response to a single array.
Expand Down
61 changes: 61 additions & 0 deletions node/tests/GlideClusterClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1488,6 +1488,67 @@ describe("GlideClusterClient", () => {
client.close();
}
});

it(
"invoke script with route invokeScriptWithRoute %p",
async () => {
const client =
await GlideClusterClient.createClient(
getClientConfigurationOption(
cluster.getAddresses(),
protocol,
),
);
const route: Routes = singleNodeRoute
? { type: "primarySlotKey", key: "1" }
: "allPrimaries";

try {
const arg = uuidv4();
const script = new Script(
Buffer.from("return {ARGV[1]}"),
);
let res = await client.invokeScriptWithRoute(
script,
{ args: [Buffer.from(arg)], route },
);

if (singleNodeRoute) {
expect(res).toEqual([arg]);
} else {
Object.values(
res as Record<string, GlideReturnType>,
).forEach((value) =>
expect(value).toEqual([arg]),
);
}

res = await client.invokeScriptWithRoute(
script,
{
args: [arg],
route,
decoder: Decoder.Bytes,
},
);

if (singleNodeRoute) {
expect(res).toEqual([Buffer.from(arg)]);
} else {
Object.values(
res as Record<string, GlideReturnType>,
).forEach((value) =>
expect(value).toEqual([
Buffer.from(arg),
]),
);
}
} finally {
client.close();
}
},
TIMEOUT,
);
},
);
it(
Expand Down
Loading