Skip to content

Commit

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

Signed-off-by: Yi-Pin Chen <[email protected]>
Signed-off-by: Chloe Yip <[email protected]>
  • Loading branch information
yipin-chen authored and cyip10 committed Jul 23, 2024
1 parent 086ca94 commit 15b6f0f
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* Node: Added LOLWUT command ([#1934](https:/valkey-io/valkey-glide/pull/1934))
* Node: Added LPOS command ([#1927](https:/valkey-io/valkey-glide/pull/1927))
* Node: Added FUNCTION LOAD command ([#1969](https:/valkey-io/valkey-glide/pull/1969))
* Node: Added FUNCTION FLUSH command ([#1984](https:/valkey-io/valkey-glide/pull/1984))

## 1.0.0 (2024-07-09)

Expand Down
11 changes: 11 additions & 0 deletions node/src/Commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1584,6 +1584,17 @@ export function createFunctionLoad(
return createCommand(RequestType.FunctionLoad, args);
}

/**
* @internal
*/
export function createFunctionFlush(mode?: FlushMode): command_request.Command {
if (mode) {
return createCommand(RequestType.FunctionFlush, [mode.toString()]);
} else {
return createCommand(RequestType.FunctionFlush, []);
}
}

export type StreamReadOptions = {
/**
* If set, the read request will block for the set amount of milliseconds or
Expand Down
21 changes: 21 additions & 0 deletions node/src/GlideClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
createEcho,
createFlushAll,
createFlushDB,
createFunctionFlush,
createFunctionLoad,
createInfo,
createLolwut,
Expand Down Expand Up @@ -415,6 +416,26 @@ export class GlideClient extends BaseClient {
);
}

/**
* Deletes all function libraries.
*
* See https://valkey.io/commands/function-flush/ for details.
*
* since Valkey version 7.0.0.
*
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* @returns A simple OK response.
*
* @example
* ```typescript
* const result = await client.functionFlush(FlushMode.SYNC);
* console.log(result); // Output: 'OK'
* ```
*/
public functionFlush(mode?: FlushMode): Promise<string> {
return this.createWritePromise(createFunctionFlush(mode));
}

/**
* Deletes all the keys of all the existing databases. This command never fails.
*
Expand Down
26 changes: 26 additions & 0 deletions node/src/GlideClusterClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
createEcho,
createFlushAll,
createFlushDB,
createFunctionFlush,
createFunctionLoad,
createInfo,
createLolwut,
Expand Down Expand Up @@ -689,6 +690,31 @@ export class GlideClusterClient extends BaseClient {
);
}

/**
* Deletes all function libraries.
*
* See https://valkey.io/commands/function-flush/ for details.
*
* since Valkey version 7.0.0.
*
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* @param route - The command will be routed to all primary node, unless `route` is provided, in which
* case the client will route the command to the nodes defined by `route`.
* @returns A simple OK response.
*
* @example
* ```typescript
* const result = await client.functionFlush(FlushMode.SYNC);
* console.log(result); // Output: 'OK'
* ```
*/
public functionFlush(mode?: FlushMode, route?: Routes): Promise<string> {
return this.createWritePromise(
createFunctionFlush(mode),
toProtobufRoute(route),
);
}

/**
* Deletes all the keys of all the existing databases. This command never fails.
*
Expand Down
15 changes: 15 additions & 0 deletions node/src/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
createExpireAt,
createFlushAll,
createFlushDB,
createFunctionFlush,
createFunctionLoad,
createGeoAdd,
createGet,
Expand Down Expand Up @@ -1866,6 +1867,20 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
return this.addAndReturn(createFunctionLoad(libraryCode, replace));
}

/**
* Deletes all function libraries.
*
* See https://valkey.io/commands/function-flush/ for details.
*
* since Valkey version 7.0.0.
*
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
* Command Response - `OK`.
*/
public functionFlush(mode?: FlushMode): T {
return this.addAndReturn(createFunctionFlush(mode));
}

/**
* Deletes all the keys of all the existing databases. This command never fails.
*
Expand Down
63 changes: 60 additions & 3 deletions node/tests/RedisClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Transaction,
} from "..";
import { RedisCluster } from "../../utils/TestUtils.js";
import { FlushMode } from "../build-ts/src/commands/FlushMode.js";
import { command_request } from "../src/ProtobufMessage";
import { checkIfServerVersionLessThan, runBaseTests } from "./SharedTests";
import {
Expand All @@ -33,7 +34,6 @@ import {
parseEndpoints,
transactionTest,
} from "./TestUtilities";
import { FlushMode } from "../build-ts/src/commands/FlushMode.js";

/* eslint-disable @typescript-eslint/no-var-requires */

Expand Down Expand Up @@ -460,9 +460,66 @@ describe("GlideClient", () => {
]),
).toEqual(2);
} finally {
expect(await client.functionFlush()).toEqual("OK");
client.close();
}
},
);

it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
"function flush test_%p",
async (protocol) => {
if (await checkIfServerVersionLessThan("7.0.0")) return;

const client = await GlideClient.createClient(
getClientConfigurationOption(cluster.getAddresses(), protocol),
);

try {
const libName = "mylib1C" + uuidv4().replaceAll("-", "");
const funcName = "myfunc1c" + uuidv4().replaceAll("-", "");
const code = generateLuaLibCode(
libName,
new Map([[funcName, "return args[1]"]]),
true,
);

// TODO use commands instead of customCommand once implemented
// verify function does not yet exist
expect(
await client.customCommand(["FUNCTION", "FLUSH"]),
).toEqual("OK");
await client.customCommand([
"FUNCTION",
"LIST",
"LIBRARYNAME",
libName,
]),
).toEqual([]);

checkSimple(await client.functionLoad(code)).toEqual(libName);

// Flush functions
expect(await client.functionFlush(FlushMode.SYNC)).toEqual(
"OK",
);
expect(await client.functionFlush(FlushMode.ASYNC)).toEqual(
"OK",
);

// TODO use commands instead of customCommand once implemented
// verify function does not yet exist
expect(
await client.customCommand([
"FUNCTION",
"LIST",
"LIBRARYNAME",
libName,
]),
).toEqual([]);

// Attempt to re-load library without overwriting to ensure FLUSH was effective
checkSimple(await client.functionLoad(code)).toEqual(libName);
} finally {
expect(await client.functionFlush()).toEqual("OK");
client.close();
}
},
Expand Down
114 changes: 110 additions & 4 deletions node/tests/RedisClusterClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
Routes,
} from "..";
import { RedisCluster } from "../../utils/TestUtils.js";
import { FlushMode } from "../build-ts/src/commands/FlushMode";
import { checkIfServerVersionLessThan, runBaseTests } from "./SharedTests";
import {
checkClusterResponse,
Expand All @@ -35,7 +36,6 @@ import {
parseEndpoints,
transactionTest,
} from "./TestUtilities";
import { FlushMode } from "../build-ts/src/commands/FlushMode";
type Context = {
client: GlideClusterClient;
};
Expand Down Expand Up @@ -675,12 +675,118 @@ describe("GlideClusterClient", () => {
(value) => expect(value).toEqual(2),
);
} finally {
expect(
expect(await client.functionFlush()).toEqual(
"OK",
);
client.close();
}
},
TIMEOUT,
);
},
);
},
);

describe.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
"Protocol is RESP2 = %s",
(protocol) => {
describe.each([true, false])(
"Single node route = %s",
(singleNodeRoute) => {
it(
"function flush",
async () => {
if (await checkIfServerVersionLessThan("7.0.0"))
return;

const client =
await GlideClusterClient.createClient(
getClientConfigurationOption(
cluster.getAddresses(),
protocol,
),
);

try {
const libName =
"mylib1C" + uuidv4().replaceAll("-", "");
const funcName =
"myfunc1c" + uuidv4().replaceAll("-", "");
const code = generateLuaLibCode(
libName,
new Map([[funcName, "return args[1]"]]),
true,
);
const route: Routes = singleNodeRoute
? { type: "primarySlotKey", key: "1" }
: "allPrimaries";

// TODO use commands instead of customCommand once implemented
// verify function does not yet exist
const functionList1 =
await client.customCommand([
"FUNCTION",
"FLUSH",
]),
"LIST",
"LIBRARYNAME",
libName,
]);
checkClusterResponse(
functionList1 as object,
singleNodeRoute,
(value) => expect(value).toEqual([]),
);

// load the library
checkSimple(
await client.functionLoad(
code,
undefined,
route,
),
).toEqual(libName);

// flush functions
expect(
await client.functionFlush(
FlushMode.SYNC,
route,
),
).toEqual("OK");
expect(
await client.functionFlush(
FlushMode.ASYNC,
route,
),
).toEqual("OK");

// TODO use commands instead of customCommand once implemented
// verify function does not exist
const functionList2 =
await client.customCommand([
"FUNCTION",
"LIST",
"LIBRARYNAME",
libName,
]);
checkClusterResponse(
functionList2 as object,
singleNodeRoute,
(value) => expect(value).toEqual([]),
);

// Attempt to re-load library without overwriting to ensure FLUSH was effective
checkSimple(
await client.functionLoad(
code,
undefined,
route,
),
).toEqual(libName);
} finally {
expect(await client.functionFlush()).toEqual(
"OK",
);
client.close();
}
},
Expand Down
10 changes: 8 additions & 2 deletions node/tests/TestUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ import {
ReturnType,
Transaction,
} from "..";
import { checkIfServerVersionLessThan } from "./SharedTests";
import { FlushMode } from "../build-ts/src/commands/FlushMode";
import { LPosOptions } from "../build-ts/src/commands/LPosOptions";
import { ListDirection } from "../build-ts/src/commands/ListDirection";
import { GeospatialData } from "../build-ts/src/commands/geospatial/GeospatialData";
import { FlushMode } from "../build-ts/src/commands/FlushMode";
import { checkIfServerVersionLessThan } from "./SharedTests";

beforeAll(() => {
Logger.init("info");
Expand Down Expand Up @@ -658,6 +658,12 @@ export async function transactionTest(
args.push(libName);
baseTransaction.functionLoad(code, true);
args.push(libName);
baseTransaction.functionFlush();
args.push("OK");
baseTransaction.functionFlush(FlushMode.ASYNC);
args.push("OK");
baseTransaction.functionFlush(FlushMode.SYNC);
args.push("OK");
}

return args;
Expand Down

0 comments on commit 15b6f0f

Please sign in to comment.