Skip to content

Commit 746bdf3

Browse files
yipin-chencyip10
authored andcommitted
Node: add FUNCTION FLUSH command (valkey-io#1984)
* Node: add FUNCTION FLUSH command Signed-off-by: Yi-Pin Chen <yi-pin.chen@improving.com>
1 parent 16c015c commit 746bdf3

File tree

8 files changed

+252
-9
lines changed

8 files changed

+252
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
* Node: Added LOLWUT command ([#1934](https://github.com/valkey-io/valkey-glide/pull/1934))
1616
* Node: Added LPOS command ([#1927](https://github.com/valkey-io/valkey-glide/pull/1927))
1717
* Node: Added FUNCTION LOAD command ([#1969](https://github.com/valkey-io/valkey-glide/pull/1969))
18+
* Node: Added FUNCTION FLUSH command ([#1984](https://github.com/valkey-io/valkey-glide/pull/1984))
1819

1920
## 1.0.0 (2024-07-09)
2021

node/src/Commands.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1584,6 +1584,17 @@ export function createFunctionLoad(
15841584
return createCommand(RequestType.FunctionLoad, args);
15851585
}
15861586

1587+
/**
1588+
* @internal
1589+
*/
1590+
export function createFunctionFlush(mode?: FlushMode): command_request.Command {
1591+
if (mode) {
1592+
return createCommand(RequestType.FunctionFlush, [mode.toString()]);
1593+
} else {
1594+
return createCommand(RequestType.FunctionFlush, []);
1595+
}
1596+
}
1597+
15871598
export type StreamReadOptions = {
15881599
/**
15891600
* If set, the read request will block for the set amount of milliseconds or

node/src/GlideClient.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
createEcho,
2424
createFlushAll,
2525
createFlushDB,
26+
createFunctionFlush,
2627
createFunctionLoad,
2728
createInfo,
2829
createLolwut,
@@ -415,6 +416,26 @@ export class GlideClient extends BaseClient {
415416
);
416417
}
417418

419+
/**
420+
* Deletes all function libraries.
421+
*
422+
* See https://valkey.io/commands/function-flush/ for details.
423+
*
424+
* since Valkey version 7.0.0.
425+
*
426+
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
427+
* @returns A simple OK response.
428+
*
429+
* @example
430+
* ```typescript
431+
* const result = await client.functionFlush(FlushMode.SYNC);
432+
* console.log(result); // Output: 'OK'
433+
* ```
434+
*/
435+
public functionFlush(mode?: FlushMode): Promise<string> {
436+
return this.createWritePromise(createFunctionFlush(mode));
437+
}
438+
418439
/**
419440
* Deletes all the keys of all the existing databases. This command never fails.
420441
*

node/src/GlideClusterClient.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
createEcho,
2424
createFlushAll,
2525
createFlushDB,
26+
createFunctionFlush,
2627
createFunctionLoad,
2728
createInfo,
2829
createLolwut,
@@ -689,6 +690,31 @@ export class GlideClusterClient extends BaseClient {
689690
);
690691
}
691692

693+
/**
694+
* Deletes all function libraries.
695+
*
696+
* See https://valkey.io/commands/function-flush/ for details.
697+
*
698+
* since Valkey version 7.0.0.
699+
*
700+
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
701+
* @param route - The command will be routed to all primary node, unless `route` is provided, in which
702+
* case the client will route the command to the nodes defined by `route`.
703+
* @returns A simple OK response.
704+
*
705+
* @example
706+
* ```typescript
707+
* const result = await client.functionFlush(FlushMode.SYNC);
708+
* console.log(result); // Output: 'OK'
709+
* ```
710+
*/
711+
public functionFlush(mode?: FlushMode, route?: Routes): Promise<string> {
712+
return this.createWritePromise(
713+
createFunctionFlush(mode),
714+
toProtobufRoute(route),
715+
);
716+
}
717+
692718
/**
693719
* Deletes all the keys of all the existing databases. This command never fails.
694720
*

node/src/Transaction.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
createExpireAt,
4141
createFlushAll,
4242
createFlushDB,
43+
createFunctionFlush,
4344
createFunctionLoad,
4445
createGeoAdd,
4546
createGet,
@@ -1866,6 +1867,20 @@ export class BaseTransaction<T extends BaseTransaction<T>> {
18661867
return this.addAndReturn(createFunctionLoad(libraryCode, replace));
18671868
}
18681869

1870+
/**
1871+
* Deletes all function libraries.
1872+
*
1873+
* See https://valkey.io/commands/function-flush/ for details.
1874+
*
1875+
* since Valkey version 7.0.0.
1876+
*
1877+
* @param mode - The flushing mode, could be either {@link FlushMode.SYNC} or {@link FlushMode.ASYNC}.
1878+
* Command Response - `OK`.
1879+
*/
1880+
public functionFlush(mode?: FlushMode): T {
1881+
return this.addAndReturn(createFunctionFlush(mode));
1882+
}
1883+
18691884
/**
18701885
* Deletes all the keys of all the existing databases. This command never fails.
18711886
*

node/tests/RedisClient.test.ts

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
Transaction,
2121
} from "..";
2222
import { RedisCluster } from "../../utils/TestUtils.js";
23+
import { FlushMode } from "../build-ts/src/commands/FlushMode.js";
2324
import { command_request } from "../src/ProtobufMessage";
2425
import { checkIfServerVersionLessThan, runBaseTests } from "./SharedTests";
2526
import {
@@ -33,7 +34,6 @@ import {
3334
parseEndpoints,
3435
transactionTest,
3536
} from "./TestUtilities";
36-
import { FlushMode } from "../build-ts/src/commands/FlushMode.js";
3737

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

@@ -460,9 +460,66 @@ describe("GlideClient", () => {
460460
]),
461461
).toEqual(2);
462462
} finally {
463+
expect(await client.functionFlush()).toEqual("OK");
464+
client.close();
465+
}
466+
},
467+
);
468+
469+
it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
470+
"function flush test_%p",
471+
async (protocol) => {
472+
if (await checkIfServerVersionLessThan("7.0.0")) return;
473+
474+
const client = await GlideClient.createClient(
475+
getClientConfigurationOption(cluster.getAddresses(), protocol),
476+
);
477+
478+
try {
479+
const libName = "mylib1C" + uuidv4().replaceAll("-", "");
480+
const funcName = "myfunc1c" + uuidv4().replaceAll("-", "");
481+
const code = generateLuaLibCode(
482+
libName,
483+
new Map([[funcName, "return args[1]"]]),
484+
true,
485+
);
486+
487+
// TODO use commands instead of customCommand once implemented
488+
// verify function does not yet exist
463489
expect(
464-
await client.customCommand(["FUNCTION", "FLUSH"]),
465-
).toEqual("OK");
490+
await client.customCommand([
491+
"FUNCTION",
492+
"LIST",
493+
"LIBRARYNAME",
494+
libName,
495+
]),
496+
).toEqual([]);
497+
498+
checkSimple(await client.functionLoad(code)).toEqual(libName);
499+
500+
// Flush functions
501+
expect(await client.functionFlush(FlushMode.SYNC)).toEqual(
502+
"OK",
503+
);
504+
expect(await client.functionFlush(FlushMode.ASYNC)).toEqual(
505+
"OK",
506+
);
507+
508+
// TODO use commands instead of customCommand once implemented
509+
// verify function does not yet exist
510+
expect(
511+
await client.customCommand([
512+
"FUNCTION",
513+
"LIST",
514+
"LIBRARYNAME",
515+
libName,
516+
]),
517+
).toEqual([]);
518+
519+
// Attempt to re-load library without overwriting to ensure FLUSH was effective
520+
checkSimple(await client.functionLoad(code)).toEqual(libName);
521+
} finally {
522+
expect(await client.functionFlush()).toEqual("OK");
466523
client.close();
467524
}
468525
},

node/tests/RedisClusterClient.test.ts

Lines changed: 110 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
Routes,
2222
} from "..";
2323
import { RedisCluster } from "../../utils/TestUtils.js";
24+
import { FlushMode } from "../build-ts/src/commands/FlushMode";
2425
import { checkIfServerVersionLessThan, runBaseTests } from "./SharedTests";
2526
import {
2627
checkClusterResponse,
@@ -35,7 +36,6 @@ import {
3536
parseEndpoints,
3637
transactionTest,
3738
} from "./TestUtilities";
38-
import { FlushMode } from "../build-ts/src/commands/FlushMode";
3939
type Context = {
4040
client: GlideClusterClient;
4141
};
@@ -675,12 +675,118 @@ describe("GlideClusterClient", () => {
675675
(value) => expect(value).toEqual(2),
676676
);
677677
} finally {
678-
expect(
678+
expect(await client.functionFlush()).toEqual(
679+
"OK",
680+
);
681+
client.close();
682+
}
683+
},
684+
TIMEOUT,
685+
);
686+
},
687+
);
688+
},
689+
);
690+
691+
describe.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])(
692+
"Protocol is RESP2 = %s",
693+
(protocol) => {
694+
describe.each([true, false])(
695+
"Single node route = %s",
696+
(singleNodeRoute) => {
697+
it(
698+
"function flush",
699+
async () => {
700+
if (await checkIfServerVersionLessThan("7.0.0"))
701+
return;
702+
703+
const client =
704+
await GlideClusterClient.createClient(
705+
getClientConfigurationOption(
706+
cluster.getAddresses(),
707+
protocol,
708+
),
709+
);
710+
711+
try {
712+
const libName =
713+
"mylib1C" + uuidv4().replaceAll("-", "");
714+
const funcName =
715+
"myfunc1c" + uuidv4().replaceAll("-", "");
716+
const code = generateLuaLibCode(
717+
libName,
718+
new Map([[funcName, "return args[1]"]]),
719+
true,
720+
);
721+
const route: Routes = singleNodeRoute
722+
? { type: "primarySlotKey", key: "1" }
723+
: "allPrimaries";
724+
725+
// TODO use commands instead of customCommand once implemented
726+
// verify function does not yet exist
727+
const functionList1 =
679728
await client.customCommand([
680729
"FUNCTION",
681-
"FLUSH",
682-
]),
730+
"LIST",
731+
"LIBRARYNAME",
732+
libName,
733+
]);
734+
checkClusterResponse(
735+
functionList1 as object,
736+
singleNodeRoute,
737+
(value) => expect(value).toEqual([]),
738+
);
739+
740+
// load the library
741+
checkSimple(
742+
await client.functionLoad(
743+
code,
744+
undefined,
745+
route,
746+
),
747+
).toEqual(libName);
748+
749+
// flush functions
750+
expect(
751+
await client.functionFlush(
752+
FlushMode.SYNC,
753+
route,
754+
),
755+
).toEqual("OK");
756+
expect(
757+
await client.functionFlush(
758+
FlushMode.ASYNC,
759+
route,
760+
),
683761
).toEqual("OK");
762+
763+
// TODO use commands instead of customCommand once implemented
764+
// verify function does not exist
765+
const functionList2 =
766+
await client.customCommand([
767+
"FUNCTION",
768+
"LIST",
769+
"LIBRARYNAME",
770+
libName,
771+
]);
772+
checkClusterResponse(
773+
functionList2 as object,
774+
singleNodeRoute,
775+
(value) => expect(value).toEqual([]),
776+
);
777+
778+
// Attempt to re-load library without overwriting to ensure FLUSH was effective
779+
checkSimple(
780+
await client.functionLoad(
781+
code,
782+
undefined,
783+
route,
784+
),
785+
).toEqual(libName);
786+
} finally {
787+
expect(await client.functionFlush()).toEqual(
788+
"OK",
789+
);
684790
client.close();
685791
}
686792
},

node/tests/TestUtilities.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import {
1818
ReturnType,
1919
Transaction,
2020
} from "..";
21-
import { checkIfServerVersionLessThan } from "./SharedTests";
21+
import { FlushMode } from "../build-ts/src/commands/FlushMode";
2222
import { LPosOptions } from "../build-ts/src/commands/LPosOptions";
2323
import { ListDirection } from "../build-ts/src/commands/ListDirection";
2424
import { GeospatialData } from "../build-ts/src/commands/geospatial/GeospatialData";
25-
import { FlushMode } from "../build-ts/src/commands/FlushMode";
25+
import { checkIfServerVersionLessThan } from "./SharedTests";
2626

2727
beforeAll(() => {
2828
Logger.init("info");
@@ -658,6 +658,12 @@ export async function transactionTest(
658658
args.push(libName);
659659
baseTransaction.functionLoad(code, true);
660660
args.push(libName);
661+
baseTransaction.functionFlush();
662+
args.push("OK");
663+
baseTransaction.functionFlush(FlushMode.ASYNC);
664+
args.push("OK");
665+
baseTransaction.functionFlush(FlushMode.SYNC);
666+
args.push("OK");
661667
}
662668

663669
return args;

0 commit comments

Comments
 (0)