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: FUNCTION DUMP and FUNCTION RESTORE in transaction #2173

Merged
Show file tree
Hide file tree
Changes from 2 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 FUNCTION DUMP and FUNCTION RESTORE commands (transaction) ([#2173](https://github.com/valkey-io/valkey-glide/pull/2173))
* Node: Added FUNCTION DUMP and FUNCTION RESTORE commands ([#2129](https://github.com/valkey-io/valkey-glide/pull/2129))
* Node: Added ZUNIONSTORE command ([#2145](https://github.com/valkey-io/valkey-glide/pull/2145))
* Node: Added XREADGROUP command ([#2124](https://github.com/valkey-io/valkey-glide/pull/2124))
Expand Down
2 changes: 1 addition & 1 deletion node/src/BaseClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ export type GlideString = string | Buffer;
/**
* Enum representing the different types of decoders.
*/
export const enum Decoder {
export enum Decoder {
/**
* Decodes the response into a buffer array.
*/
Expand Down
31 changes: 31 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
FlushMode,
FunctionListOptions,
FunctionListResponse, // eslint-disable-line @typescript-eslint/no-unused-vars
FunctionRestorePolicy,
FunctionStatsSingleResponse, // eslint-disable-line @typescript-eslint/no-unused-vars
GeoAddOptions,
GeoBoxShape, // eslint-disable-line @typescript-eslint/no-unused-vars
Expand Down Expand Up @@ -97,9 +98,11 @@ import {
createFlushAll,
createFlushDB,
createFunctionDelete,
createFunctionDump,
createFunctionFlush,
createFunctionList,
createFunctionLoad,
createFunctionRestore,
createFunctionStats,
createGeoAdd,
createGeoDist,
Expand Down Expand Up @@ -3208,6 +3211,34 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createFunctionStats());
}

/**
* Returns the serialized payload of all loaded libraries.
*
* @see {@link https://valkey.io/commands/function-dump/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
* @remarks To execute a transaction with a `functionDump` command, the `exec` command requires `Decoder.Bytes` to handle the response.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought we were going to go with the same solution as Java?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes we have a task for this

*
* Command Response - The serialized payload of all loaded libraries.
*/
public functionDump(): T {
return this.addAndReturn(createFunctionDump());
}

/**
* Restores libraries from the serialized payload returned by {@link functionDump}.
*
* @see {@link https://valkey.io/commands/function-restore/|valkey.io} for details.
* @remarks Since Valkey version 7.0.0.
*
* @param payload - The serialized data from {@link functionDump}.
* @param policy - (Optional) A policy for handling existing libraries.
*
* Command Response - `"OK"`.
*/
public functionRestore(payload: Buffer, policy?: FunctionRestorePolicy): T {
return this.addAndReturn(createFunctionRestore(payload, policy));
}

/**
* Deletes all the keys of all the existing databases. This command never fails.
*
Expand Down
40 changes: 40 additions & 0 deletions node/tests/GlideClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,46 @@ describe("GlideClient", () => {
},
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
"function dump function restore in transaction %p",
async (protocol) => {
if (cluster.checkIfServerVersionLessThan("7.0.0")) return;

const config = getClientConfigurationOption(
cluster.getAddresses(),
protocol,
);
const client = await GlideClient.createClient(config);
expect(await client.functionFlush()).toEqual("OK");

try {
const name1 = "Foster";
const name2 = "Dogster";
// function returns first argument
const code = generateLuaLibCode(
name1,
new Map([[name2, "return args[1]"]]),
false,
);
expect(await client.functionLoad(code)).toEqual(name1);

// Verify functionDump
let transaction = new Transaction().functionDump();
const result = await client.exec(transaction, Decoder.Bytes);
const data = result?.[0] as Buffer;

// Verify functionRestore
transaction = new Transaction()
.functionRestore(data, FunctionRestorePolicy.REPLACE)
.fcall(name2, [], ["meow"]);
expect(await client.exec(transaction)).toEqual(["OK", "meow"]);
} finally {
expect(await client.functionFlush()).toEqual("OK");
client.close();
}
},
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
"sort sortstore sort_store sortro sort_ro sortreadonly test_%p",
async (protocol) => {
Expand Down
41 changes: 41 additions & 0 deletions node/tests/GlideClusterClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,47 @@ describe("GlideClusterClient", () => {
},
TIMEOUT,
);
it("function dump function restore in transaction %p", async () => {
if (cluster.checkIfServerVersionLessThan("7.0.0")) return;

const config = getClientConfigurationOption(
cluster.getAddresses(),
protocol,
);
const client = await GlideClusterClient.createClient(config);
expect(await client.functionFlush()).toEqual("OK");

try {
const name1 = "Foster";
const name2 = "Dogster";
// function returns first argument
const code = generateLuaLibCode(
name1,
new Map([[name2, "return args[1]"]]),
false,
);
expect(await client.functionLoad(code)).toEqual(name1);

// Verify functionDump
let transaction = new ClusterTransaction().functionDump();
const result = await client.exec(transaction, {
decoder: Decoder.Bytes,
});
const data = result?.[0] as Buffer;

// Verify functionRestore
transaction = new ClusterTransaction()
.functionRestore(data, FunctionRestorePolicy.REPLACE)
.fcall(name2, [], ["meow"]);
expect(await client.exec(transaction)).toEqual([
"OK",
"meow",
]);
} finally {
expect(await client.functionFlush()).toEqual("OK");
client.close();
}
});
},
);

Expand Down
Loading