Skip to content

Commit

Permalink
added lua scripts support in node.
Browse files Browse the repository at this point in the history
  • Loading branch information
Adan committed Jan 11, 2024
1 parent 3e81825 commit 8c15405
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 4 deletions.
2 changes: 2 additions & 0 deletions node/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export { Script } from "glide-rs";
export {
BaseClientConfiguration,
ProtocolVersion,
ReturnType,
ScriptOptions,
} from "./src/BaseClient";
export {
ExpireOptions,
Expand Down
67 changes: 63 additions & 4 deletions node/src/BaseClient.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
DEFAULT_TIMEOUT_IN_MILLISECONDS,
Script,
StartSocketConnection,
valueFromSplitPointer,
} from "glide-rs";
Expand Down Expand Up @@ -154,6 +155,17 @@ export type BaseClientConfiguration = {
clientName?: string;
};

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

function getRequestErrorClass(
type: response.RequestErrorType | null | undefined
): typeof RequestError {
Expand Down Expand Up @@ -297,8 +309,9 @@ export class BaseClient {
* @internal
*/
protected createWritePromise<T>(
command: redis_request.Command | redis_request.Command[],
route?: redis_request.Routes
command?: redis_request.Command | redis_request.Command[],
route?: redis_request.Routes,
message?: redis_request.RedisRequest
): Promise<T> {
if (this.isClosed) {
throw new ClosingError(
Expand All @@ -307,9 +320,21 @@ export class BaseClient {
}

return new Promise((resolve, reject) => {
const callbackIndex = this.getCallbackIndex();
const callbackIndex = message
? message.callbackIdx
: this.getCallbackIndex();
this.promiseCallbackFunctions[callbackIndex] = [resolve, reject];
this.writeOrBufferRedisRequest(callbackIndex, command, route);
command
? this.writeOrBufferRedisRequest(callbackIndex, command, route)
: this.writeOrBufferRequest(
message as redis_request.RedisRequest,
(message: redis_request.RedisRequest, writer: Writer) => {
redis_request.RedisRequest.encodeDelimited(
message,
writer
);
}
);
});
}

Expand Down Expand Up @@ -888,6 +913,40 @@ export class BaseClient {
return this.createWritePromise(createTTL(key));
}

/** Invokes a Lua script with its keys and arguments.
* This method simplifies the process of invoking scripts on a Redis server by using an object that represents a LUA script.
* The `Script` object is immutable and can be shared.
* 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 Redis `SCRIPT LOAD` command. After that, it can be invoked using the Redis `EVALSHA` command
*
* @param script - The Lua script to execute.
* @param options - The script option that contains keys and arguments for the script.
* @returns a value that depends on the script that was executed.
*
* @example
* const luaScript = "return \{ KEYS[1], ARGV[1] \}";
* const scriptOptions = \{
* keys: ["foo"],
* args: ["bar"],
* \};
* await invokeScript(luaScript, scriptOptions);
* ["foo", "bar"]
*/
public invokeScript(
script: Script,
option?: ScriptOptions
): Promise<ReturnType> {
const message = redis_request.RedisRequest.create({
callbackIdx: this.getCallbackIndex(),
scriptInvocation: redis_request.ScriptInvocation.create({
hash: script.getHash(),
keys: option?.keys,
args: option?.args,
}),
});
return this.createWritePromise(undefined, undefined, message);
}

private readonly MAP_READ_FROM_STRATEGY: Record<
ReadFrom,
connection_request.ReadFrom
Expand Down
42 changes: 42 additions & 0 deletions node/tests/SharedTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ProtocolVersion,
RedisClient,
RedisClusterClient,
Script,
parseInfoResponse,
} from "../";
import { Client, GetAndSetRandomValue, getFirstResult } from "./TestUtilities";
Expand Down Expand Up @@ -1203,6 +1204,47 @@ export function runBaseTests<Context>(config: {
},
config.timeout
);

it(
"script test",
async () => {
await runTest(async (client: BaseClient) => {
const key1 = uuidv4();
const key2 = uuidv4();

let script = new Script("return 'Hello'");
expect(await client.invokeScript(script)).toEqual("Hello");

script = new Script(
"return redis.call('SET', KEYS[1], ARGV[1])"
);
expect(
await client.invokeScript(script, {
keys: [key1],
args: ["bar"],
})
).toEqual("OK");

/// Reuse the same script with different parameters.
expect(
await client.invokeScript(script, {
keys: [key2],
args: ["bar"],
})
).toEqual("OK");

script = new Script("return redis.call('GET', KEYS[1])");
expect(
await client.invokeScript(script, { keys: [key1] })
).toEqual("bar");

expect(
await client.invokeScript(script, { keys: [key2] })
).toEqual("bar");
});
},
config.timeout
);
}

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

0 comments on commit 8c15405

Please sign in to comment.