From 33681cec2f3654bdfbc2e9474c1a1c0e97b7c2b6 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Fri, 26 Jul 2024 12:14:22 -0700 Subject: [PATCH 1/9] Node: added COPY command Signed-off-by: Yi-Pin Chen --- node/src/BaseClient.ts | 31 ++++++++++++ node/src/Commands.ts | 23 +++++++++ node/src/GlideClient.ts | 32 +++++++++++++ node/src/Transaction.ts | 27 +++++++++++ node/tests/RedisClient.test.ts | 86 ++++++++++++++++++++++++++++++++++ node/tests/SharedTests.ts | 72 +++++++++++++++++++++++----- node/tests/TestUtilities.ts | 8 +++- 7 files changed, 266 insertions(+), 13 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 429115b4e8..a14ab0018c 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -31,6 +31,7 @@ import { createBRPop, createBitCount, createBitOp, + createCopy, createDecr, createDecrBy, createDel, @@ -3369,6 +3370,36 @@ export class BaseClient { return this.createWritePromise(createObjectRefcount(key)); } + /** + * Copies the value stored at the `source` to the `destination` key if the `destination` key does not + * yet exist. + * + * See https://valkey.io/commands/copy/ for more details. + * + * since Valkey version 6.2.0. + * + * @remarks When in cluster mode, `source` and `destination` must map to the same hash slot. + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param replace - If the destination key should be removed before copying the value to it. + * @returns `true` if `source` was copied, `false` if the `source` was not copied. + * + * @example + * ```typescript + * const result = await client.copy("set1", "set2", true); + * console.log(result); // Output: true - "set1" was copied to "set2". + * ``` + */ + public async copy( + source: string, + destination: string, + replace?: boolean, + ): Promise { + return this.createWritePromise( + createCopy(source, destination, undefined, replace), + ); + } + /** * Invokes a previously loaded function. * diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 7b40948d0f..750f2cfe24 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1860,6 +1860,29 @@ export function createFlushDB(mode?: FlushMode): command_request.Command { } } +/** + * + * @internal + */ +export function createCopy( + source: string, + destination: string, + destinationDB?: number, + replace?: boolean, +): command_request.Command { + let args: string[] = [source, destination]; + + if (destinationDB) { + args = args.concat("DB", destinationDB.toString()); + } + + if (replace) { + args.push("REPLACE"); + } + + return createCommand(RequestType.Copy, args); +} + /** * @internal */ diff --git a/node/src/GlideClient.ts b/node/src/GlideClient.ts index b89e39a6c4..49185597e3 100644 --- a/node/src/GlideClient.ts +++ b/node/src/GlideClient.ts @@ -18,6 +18,7 @@ import { createConfigResetStat, createConfigRewrite, createConfigSet, + createCopy, createCustomCommand, createDBSize, createEcho, @@ -371,6 +372,37 @@ export class GlideClient extends BaseClient { return this.createWritePromise(createTime()); } + /** + * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` + * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * + * See https://valkey.io/commands/copy/ for more details. + * + * since Valkey version 6.2.0. + * + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param destinationDB - The alternative logical database index for the destination key. + * @param replace - If the destination key should be removed before copying the value to it. + * @returns `true` if `source` was copied, `false` if the `source` was not copied. + * + * @example + * ```typescript + * const result = await client.copy("set1", "set2", 1, false); + * console.log(result); // Output: true - "set1" was copied to "set2". + * ``` + */ + public async copyDB( + source: string, + destination: string, + destinationDB?: number, + replace?: boolean, + ): Promise { + return this.createWritePromise( + createCopy(source, destination, destinationDB, replace), + ); + } + /** * Displays a piece of generative computer art and the server version. * diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index fb56e7ff93..e7f089f6b6 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -31,6 +31,7 @@ import { createConfigResetStat, createConfigRewrite, createConfigSet, + createCopy, createCustomCommand, createDBSize, createDecr, @@ -1865,6 +1866,32 @@ export class BaseTransaction> { return this.addAndReturn(createObjectRefcount(key)); } + /** + * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` + * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * + * See https://valkey.io/commands/copy/ for more details. + * + * since Valkey version 6.2.0. + * + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param destinationDB - The alternative logical database index for the destination key. + * @param replace - If the destination key should be removed before copying the value to it. + * + * Command Response - `true` if `source` was copied, `false` if the `source` was not copied. + */ + public copy( + source: string, + destination: string, + destinationDB?: number, // ychen - should I remove this since copy with DB doesn't work under cluster mode + replace?: boolean, + ): T { + return this.addAndReturn( + createCopy(source, destination, destinationDB, replace), + ); + } + /** * Displays a piece of generative computer art and the server version. * diff --git a/node/tests/RedisClient.test.ts b/node/tests/RedisClient.test.ts index 09ac745aeb..ca39db9c28 100644 --- a/node/tests/RedisClient.test.ts +++ b/node/tests/RedisClient.test.ts @@ -365,6 +365,92 @@ describe("GlideClient", () => { TIMEOUT, ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + "copy with DB test_%p", + async (protocol) => { + if (cluster.checkIfServerVersionLessThan("6.2.0")) return; + + const client = await GlideClient.createClient( + getClientConfigurationOption(cluster.getAddresses(), protocol), + ); + + const source = `{key}-${uuidv4()}`; + const destination = `{key}-${uuidv4()}`; + const value1 = uuidv4(); + const value2 = uuidv4(); + const index0 = 0; + const index1 = 1; + const index2 = 2; + + try { + // neither key exists + checkSimple( + await client.copyDB(source, destination, index1, false), + ).toEqual(false); + + // source exists, destination does not + expect(await client.set(source, value1)).toEqual("OK"); + checkSimple( + await client.copyDB(source, destination, index1, false), + ).toEqual(true); + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value1); + + // new value for source key + expect(await client.select(index0)).toEqual("OK"); + expect(await client.set(source, value2)).toEqual("OK"); + + // no REPLACE, copying to existing key on DB 0 & 1, non-existing key on DB 2 + checkSimple( + await client.copyDB(source, destination, index1, false), + ).toEqual(false); + checkSimple( + await client.copyDB(source, destination, index2, false), + ).toEqual(true); + + // new value only gets copied to DB 2 + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value1); + expect(await client.select(index2)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value2); + + // both exists, with REPLACE, when value isn't the same, source always get copied to + // destination + expect(await client.select(index0)).toEqual("OK"); + checkSimple( + await client.copyDB(source, destination, index1, true), + ).toEqual(true); + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value2); + } finally { + // switching back to db 0 + await client.select(index0); + } + + // transaction tests + try { + const transaction = new Transaction(); + transaction.select(index1); + transaction.set(source, value1); + transaction.copy(source, destination, index1, true); + transaction.get(destination); + const results = await client.exec(transaction); + + if (results != null) { + checkSimple(results.length).toEqual(4); + checkSimple(results[2]).toEqual(true); + checkSimple(results[3]).toEqual(value1); + } + } finally { + // switching back to db 0 + await client.select(index0); + } + + client.close(); + }, + TIMEOUT, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( "function load test_%p", async (protocol) => { diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index cc215cd164..01ab600b75 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -13,6 +13,7 @@ import { BitwiseOperation, ClosingError, ExpireOptions, + GeoUnit, GlideClient, GlideClusterClient, InfoOptions, @@ -22,8 +23,18 @@ import { ScoreFilter, Script, parseInfoResponse, - GeoUnit, } from "../"; +import { RedisCluster } from "../../utils/TestUtils"; +import { SingleNodeRoute } from "../build-ts/src/GlideClusterClient"; +import { + BitOffsetOptions, + BitmapIndexType, +} from "../build-ts/src/commands/BitOffsetOptions"; +import { ConditionalChange } from "../build-ts/src/commands/ConditionalChange"; +import { FlushMode } from "../build-ts/src/commands/FlushMode"; +import { LPosOptions } from "../build-ts/src/commands/LPosOptions"; +import { GeoAddOptions } from "../build-ts/src/commands/geospatial/GeoAddOptions"; +import { GeospatialData } from "../build-ts/src/commands/geospatial/GeospatialData"; import { Client, GetAndSetRandomValue, @@ -33,17 +44,6 @@ import { intoArray, intoString, } from "./TestUtilities"; -import { SingleNodeRoute } from "../build-ts/src/GlideClusterClient"; -import { - BitmapIndexType, - BitOffsetOptions, -} from "../build-ts/src/commands/BitOffsetOptions"; -import { LPosOptions } from "../build-ts/src/commands/LPosOptions"; -import { GeospatialData } from "../build-ts/src/commands/geospatial/GeospatialData"; -import { GeoAddOptions } from "../build-ts/src/commands/geospatial/GeoAddOptions"; -import { ConditionalChange } from "../build-ts/src/commands/ConditionalChange"; -import { FlushMode } from "../build-ts/src/commands/FlushMode"; -import { RedisCluster } from "../../utils/TestUtils"; export type BaseClient = GlideClient | GlideClusterClient; @@ -4250,6 +4250,54 @@ export function runBaseTests(config: { config.timeout, ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + "copy test_%p", + async (protocol) => { + await runTest(async (client: BaseClient, cluster: RedisCluster) => { + if (cluster.checkIfServerVersionLessThan("6.2.0")) return; + + const source = `{key}-${uuidv4()}`; + const destination = `{key}-${uuidv4()}`; + const value1 = uuidv4(); + const value2 = uuidv4(); + + // neither key exists + checkSimple( + await client.copy(source, destination, false), + ).toEqual(false); + checkSimple(await client.copy(source, destination)).toEqual( + false, + ); + + // source exists, destination does not + expect(await client.set(source, value1)).toEqual("OK"); + checkSimple( + await client.copy(source, destination, false), + ).toEqual(true); + checkSimple(await client.get(destination)).toEqual(value1); + + // new value for source key + expect(await client.set(source, value2)).toEqual("OK"); + + // both exists, no REPLACE + checkSimple(await client.copy(source, destination)).toEqual( + false, + ); + checkSimple( + await client.copy(source, destination, false), + ).toEqual(false); + checkSimple(await client.get(destination)).toEqual(value1); + + // both exists, with REPLACE + checkSimple( + await client.copy(source, destination, true), + ).toEqual(true); + checkSimple(await client.get(destination)).toEqual(value2); + }, protocol); + }, + config.timeout, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( `flushall test_%p`, async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index a230562ced..ef656c42d5 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -5,8 +5,8 @@ import { beforeAll, expect } from "@jest/globals"; import { exec } from "child_process"; import parseArgs from "minimist"; -import { v4 as uuidv4 } from "uuid"; import { gte } from "semver"; +import { v4 as uuidv4 } from "uuid"; import { BaseClient, BaseClientConfiguration, @@ -697,6 +697,12 @@ export async function transactionTest( 'xtrim(key9, { method: "minid", threshold: "0-2", exact: true }', 1, ]); + + if (gte("6.2.0", version)) { + baseTransaction.copy(key9, key10, undefined, true); + responseData.push(["copy(key9, key10, undefined, true)", true]); + } + baseTransaction.rename(key9, key10); responseData.push(["rename(key9, key10)", "OK"]); baseTransaction.exists([key10]); From 23770a9d2d3735d4573d6a00085a71da2c430676 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Fri, 26 Jul 2024 12:16:48 -0700 Subject: [PATCH 2/9] Updated CHANGELOG.md Signed-off-by: Yi-Pin Chen --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 633798767f..cafc262b20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * Node: Added FUNCTION DELETE command ([#1990](https://github.com/valkey-io/valkey-glide/pull/1990)) * Node: Added FUNCTION FLUSH command ([#1984](https://github.com/valkey-io/valkey-glide/pull/1984)) * Node: Added FCALL and FCALL_RO commands ([#2011](https://github.com/valkey-io/valkey-glide/pull/2011)) +* Node: Added COPY command ([#2024](https://github.com/valkey-io/valkey-glide/pull/2024)) * Node: Added ZMPOP command ([#1994](https://github.com/valkey-io/valkey-glide/pull/1994)) #### Fixes From ef0260c23d0ddec296097ff96ad90a24458ebda5 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Fri, 26 Jul 2024 17:34:39 -0700 Subject: [PATCH 3/9] Addressed review comment Signed-off-by: Yi-Pin Chen --- node/src/BaseClient.ts | 11 ++++++----- node/src/Commands.ts | 2 +- node/src/GlideClient.ts | 15 +++++++++------ node/src/Transaction.ts | 15 ++++++++------- node/tests/RedisClient.test.ts | 2 +- node/tests/RedisClusterClient.test.ts | 3 ++- 6 files changed, 27 insertions(+), 21 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 253a0f9c87..88bfdc6060 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -3496,19 +3496,20 @@ export class BaseClient { } /** - * Copies the value stored at the `source` to the `destination` key if the `destination` key does not - * yet exist. + * Copies the value stored at the `source` to the `destination` key. When `replace` is `true`, + * removes the `destination` key first if it already exists, otherwise performs no action. * * See https://valkey.io/commands/copy/ for more details. * - * since Valkey version 6.2.0. - * * @remarks When in cluster mode, `source` and `destination` must map to the same hash slot. * @param source - The key to the source value. * @param destination - The key where the value should be copied to. - * @param replace - If the destination key should be removed before copying the value to it. + * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. * @returns `true` if `source` was copied, `false` if the `source` was not copied. * + * since Valkey version 6.2.0. + * * @example * ```typescript * const result = await client.copy("set1", "set2", true); diff --git a/node/src/Commands.ts b/node/src/Commands.ts index 255e01017b..b47e3eebd8 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1994,7 +1994,7 @@ export function createCopy( ): command_request.Command { let args: string[] = [source, destination]; - if (destinationDB) { + if (destinationDB !== undefined) { args = args.concat("DB", destinationDB.toString()); } diff --git a/node/src/GlideClient.ts b/node/src/GlideClient.ts index 5265bf752c..c99d4c7ce8 100644 --- a/node/src/GlideClient.ts +++ b/node/src/GlideClient.ts @@ -373,19 +373,22 @@ export class GlideClient extends BaseClient { } /** - * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` - * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * Copies the value stored at the `source` to the `destination` key. If `destinationDB` is specified, + * the value will be copied to the databased specified, otherwise the current database will be used. + * When `replace` is true, removes the `destination` key first if it already exists, otherwise performs + * no action. * * See https://valkey.io/commands/copy/ for more details. * - * since Valkey version 6.2.0. - * * @param source - The key to the source value. * @param destination - The key where the value should be copied to. - * @param destinationDB - The alternative logical database index for the destination key. - * @param replace - If the destination key should be removed before copying the value to it. + * @param destinationDB - (Optional) The alternative logical database index for the destination key. + * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. * @returns `true` if `source` was copied, `false` if the `source` was not copied. * + * since Valkey version 6.2.0. + * * @example * ```typescript * const result = await client.copy("set1", "set2", 1, false); diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 034feec8a8..09f77933e3 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -10,8 +10,8 @@ import { ExpireOptions, FlushMode, GeoAddOptions, - GeospatialData, GeoUnit, + GeospatialData, InfoOptions, InsertPosition, KeyWeight, @@ -143,6 +143,7 @@ import { createZDiff, createZDiffStore, createZDiffWithScores, + createZIncrBy, createZInterCard, createZInterstore, createZMPop, @@ -158,7 +159,6 @@ import { createZRevRank, createZRevRankWithScore, createZScore, - createZIncrBy, } from "./Commands"; import { command_request } from "./ProtobufMessage"; @@ -1958,19 +1958,20 @@ export class BaseTransaction> { * * See https://valkey.io/commands/copy/ for more details. * - * since Valkey version 6.2.0. - * * @param source - The key to the source value. * @param destination - The key where the value should be copied to. - * @param destinationDB - The alternative logical database index for the destination key. - * @param replace - If the destination key should be removed before copying the value to it. + * @param destinationDB - (Optional) The alternative logical database index for the destination key. + * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. * * Command Response - `true` if `source` was copied, `false` if the `source` was not copied. + * + * since Valkey version 6.2.0. */ public copy( source: string, destination: string, - destinationDB?: number, // ychen - should I remove this since copy with DB doesn't work under cluster mode + destinationDB?: number, replace?: boolean, ): T { return this.addAndReturn( diff --git a/node/tests/RedisClient.test.ts b/node/tests/RedisClient.test.ts index ab0e96c5e7..359e3a1be9 100644 --- a/node/tests/RedisClient.test.ts +++ b/node/tests/RedisClient.test.ts @@ -400,7 +400,7 @@ describe("GlideClient", () => { expect(await client.select(index0)).toEqual("OK"); expect(await client.set(source, value2)).toEqual("OK"); - // no REPLACE, copying to existing key on DB 0 & 1, non-existing key on DB 2 + // no REPLACE, copying to existing key on DB 1, non-existing key on DB 2 checkSimple( await client.copyDB(source, destination, index1, false), ).toEqual(false); diff --git a/node/tests/RedisClusterClient.test.ts b/node/tests/RedisClusterClient.test.ts index b60f064b69..370abf987c 100644 --- a/node/tests/RedisClusterClient.test.ts +++ b/node/tests/RedisClusterClient.test.ts @@ -21,8 +21,8 @@ import { Routes, ScoreFilter, } from ".."; -import { FlushMode } from "../build-ts/src/Commands"; import { RedisCluster } from "../../utils/TestUtils.js"; +import { FlushMode } from "../build-ts/src/Commands"; import { runBaseTests } from "./SharedTests"; import { checkClusterResponse, @@ -325,6 +325,7 @@ describe("GlideClusterClient", () => { client.zdiff(["abc", "zxy", "lkn"]), client.zdiffWithScores(["abc", "zxy", "lkn"]), client.zdiffstore("abc", ["zxy", "lkn"]), + client.copy("abc", "zxy", true), ); } From 58fc3be31484e124caf4f71c5848ef9e82f91462 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 10:48:52 -0700 Subject: [PATCH 4/9] Minor reworks on transacation Signed-off-by: Yi-Pin Chen --- node/src/BaseClient.ts | 32 ------- node/src/Commands.ts | 15 +-- node/src/GlideClient.ts | 11 +-- node/src/GlideClusterClient.ts | 32 +++++++ node/src/Transaction.ts | 74 +++++++++------ node/tests/RedisClient.test.ts | 126 +++++++++++++------------- node/tests/RedisClusterClient.test.ts | 58 +++++++++++- node/tests/SharedTests.ts | 48 ---------- node/tests/TestUtilities.ts | 7 +- 9 files changed, 215 insertions(+), 188 deletions(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 88bfdc6060..8a8d4610aa 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -39,7 +39,6 @@ import { createBitCount, createBitOp, createBitPos, - createCopy, createDecr, createDecrBy, createDel, @@ -3495,37 +3494,6 @@ export class BaseClient { return this.createWritePromise(createObjectRefcount(key)); } - /** - * Copies the value stored at the `source` to the `destination` key. When `replace` is `true`, - * removes the `destination` key first if it already exists, otherwise performs no action. - * - * See https://valkey.io/commands/copy/ for more details. - * - * @remarks When in cluster mode, `source` and `destination` must map to the same hash slot. - * @param source - The key to the source value. - * @param destination - The key where the value should be copied to. - * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the - * value to it. If not provided, no action will be performed if the key already exists. - * @returns `true` if `source` was copied, `false` if the `source` was not copied. - * - * since Valkey version 6.2.0. - * - * @example - * ```typescript - * const result = await client.copy("set1", "set2", true); - * console.log(result); // Output: true - "set1" was copied to "set2". - * ``` - */ - public async copy( - source: string, - destination: string, - replace?: boolean, - ): Promise { - return this.createWritePromise( - createCopy(source, destination, undefined, replace), - ); - } - /** * Invokes a previously loaded function. * diff --git a/node/src/Commands.ts b/node/src/Commands.ts index b47e3eebd8..240c2f4a81 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -1989,17 +1989,18 @@ export function createFlushDB(mode?: FlushMode): command_request.Command { export function createCopy( source: string, destination: string, - destinationDB?: number, - replace?: boolean, + options?: { destinationDB?: number; replace?: boolean }, ): command_request.Command { let args: string[] = [source, destination]; - if (destinationDB !== undefined) { - args = args.concat("DB", destinationDB.toString()); - } + if (options) { + if (options.destinationDB !== undefined) { + args = args.concat("DB", options.destinationDB.toString()); + } - if (replace) { - args.push("REPLACE"); + if (options.replace) { + args.push("REPLACE"); + } } return createCommand(RequestType.Copy, args); diff --git a/node/src/GlideClient.ts b/node/src/GlideClient.ts index c99d4c7ce8..6ebc94d162 100644 --- a/node/src/GlideClient.ts +++ b/node/src/GlideClient.ts @@ -383,7 +383,7 @@ export class GlideClient extends BaseClient { * @param source - The key to the source value. * @param destination - The key where the value should be copied to. * @param destinationDB - (Optional) The alternative logical database index for the destination key. - * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the + * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the * value to it. If not provided, no action will be performed if the key already exists. * @returns `true` if `source` was copied, `false` if the `source` was not copied. * @@ -391,18 +391,17 @@ export class GlideClient extends BaseClient { * * @example * ```typescript - * const result = await client.copy("set1", "set2", 1, false); + * const result = await client.copy("set1", "set2", { destinationDB: 1, replace: false }); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` */ - public async copyDB( + public async copy( source: string, destination: string, - destinationDB?: number, - replace?: boolean, + options?: { destinationDB?: number; replace?: boolean }, ): Promise { return this.createWritePromise( - createCopy(source, destination, destinationDB, replace), + createCopy(source, destination, options), ); } diff --git a/node/src/GlideClusterClient.ts b/node/src/GlideClusterClient.ts index 632132a3e0..3448cd1cf9 100644 --- a/node/src/GlideClusterClient.ts +++ b/node/src/GlideClusterClient.ts @@ -19,6 +19,7 @@ import { createConfigResetStat, createConfigRewrite, createConfigSet, + createCopy, createCustomCommand, createDBSize, createEcho, @@ -635,6 +636,37 @@ export class GlideClusterClient extends BaseClient { return this.createWritePromise(createTime(), toProtobufRoute(route)); } + /** + * Copies the value stored at the `source` to the `destination` key. When `replace` is `true`, + * removes the `destination` key first if it already exists, otherwise performs no action. + * + * See https://valkey.io/commands/copy/ for more details. + * + * @remarks When in cluster mode, `source` and `destination` must map to the same hash slot. + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. + * @returns `true` if `source` was copied, `false` if the `source` was not copied. + * + * since Valkey version 6.2.0. + * + * @example + * ```typescript + * const result = await client.copy("set1", "set2", { replace: true }); + * console.log(result); // Output: true - "set1" was copied to "set2". + * ``` + */ + public async copy( + source: string, + destination: string, + options?: { replace?: boolean }, + ): Promise { + return this.createWritePromise( + createCopy(source, destination, options), + ); + } + /** * Displays a piece of generative computer art and the server version. * diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index 09f77933e3..05db861fd0 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -1952,33 +1952,6 @@ export class BaseTransaction> { return this.addAndReturn(createObjectRefcount(key)); } - /** - * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` - * is true, removes the `destination` key first if it already exists, otherwise performs no action. - * - * See https://valkey.io/commands/copy/ for more details. - * - * @param source - The key to the source value. - * @param destination - The key where the value should be copied to. - * @param destinationDB - (Optional) The alternative logical database index for the destination key. - * @param replace - (Optional) If `ture`, the `destination` key should be removed before copying the - * value to it. If not provided, no action will be performed if the key already exists. - * - * Command Response - `true` if `source` was copied, `false` if the `source` was not copied. - * - * since Valkey version 6.2.0. - */ - public copy( - source: string, - destination: string, - destinationDB?: number, - replace?: boolean, - ): T { - return this.addAndReturn( - createCopy(source, destination, destinationDB, replace), - ); - } - /** * Displays a piece of generative computer art and the server version. * @@ -2330,6 +2303,30 @@ export class Transaction extends BaseTransaction { public select(index: number): Transaction { return this.addAndReturn(createSelect(index)); } + + /** + * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` + * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * + * See https://valkey.io/commands/copy/ for more details. + * + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param destinationDB - (Optional) The alternative logical database index for the destination key. + * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. + * + * Command Response - `true` if `source` was copied, `false` if the `source` was not copied. + * + * since Valkey version 6.2.0. + */ + public copy( + source: string, + destination: string, + options?: { destinationDB?: number; replace?: boolean }, + ): Transaction { + return this.addAndReturn(createCopy(source, destination, options)); + } } /** @@ -2345,4 +2342,27 @@ export class Transaction extends BaseTransaction { */ export class ClusterTransaction extends BaseTransaction { /// TODO: add all CLUSTER commands + + /** + * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` + * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * + * See https://valkey.io/commands/copy/ for more details. + * + * @param source - The key to the source value. + * @param destination - The key where the value should be copied to. + * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the + * value to it. If not provided, no action will be performed if the key already exists. + * + * Command Response - `true` if `source` was copied, `false` if the `source` was not copied. + * + * since Valkey version 6.2.0. + */ + public copy( + source: string, + destination: string, + options?: { replace?: boolean }, + ): ClusterTransaction { + return this.addAndReturn(createCopy(source, destination, options)); + } } diff --git a/node/tests/RedisClient.test.ts b/node/tests/RedisClient.test.ts index 359e3a1be9..88d933bb1d 100644 --- a/node/tests/RedisClient.test.ts +++ b/node/tests/RedisClient.test.ts @@ -382,69 +382,73 @@ describe("GlideClient", () => { const index1 = 1; const index2 = 2; - try { - // neither key exists - checkSimple( - await client.copyDB(source, destination, index1, false), - ).toEqual(false); - - // source exists, destination does not - expect(await client.set(source, value1)).toEqual("OK"); - checkSimple( - await client.copyDB(source, destination, index1, false), - ).toEqual(true); - expect(await client.select(index1)).toEqual("OK"); - checkSimple(await client.get(destination)).toEqual(value1); - - // new value for source key - expect(await client.select(index0)).toEqual("OK"); - expect(await client.set(source, value2)).toEqual("OK"); + // neither key exists + checkSimple( + await client.copy(source, destination, { + destinationDB: index1, + replace: false, + }), + ).toEqual(false); + + // source exists, destination does not + expect(await client.set(source, value1)).toEqual("OK"); + checkSimple( + await client.copy(source, destination, { + destinationDB: index1, + replace: false, + }), + ).toEqual(true); + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value1); + + // new value for source key + expect(await client.select(index0)).toEqual("OK"); + expect(await client.set(source, value2)).toEqual("OK"); + + // no REPLACE, copying to existing key on DB 1, non-existing key on DB 2 + checkSimple( + await client.copy(source, destination, { + destinationDB: index1, + replace: false, + }), + ).toEqual(false); + checkSimple( + await client.copy(source, destination, { + destinationDB: index2, + replace: false, + }), + ).toEqual(true); + + // new value only gets copied to DB 2 + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value1); + expect(await client.select(index2)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value2); + + // both exists, with REPLACE, when value isn't the same, source always get copied to + // destination + expect(await client.select(index0)).toEqual("OK"); + checkSimple( + await client.copy(source, destination, { + destinationDB: index1, + replace: true, + }), + ).toEqual(true); + expect(await client.select(index1)).toEqual("OK"); + checkSimple(await client.get(destination)).toEqual(value2); - // no REPLACE, copying to existing key on DB 1, non-existing key on DB 2 - checkSimple( - await client.copyDB(source, destination, index1, false), - ).toEqual(false); - checkSimple( - await client.copyDB(source, destination, index2, false), - ).toEqual(true); - - // new value only gets copied to DB 2 - expect(await client.select(index1)).toEqual("OK"); - checkSimple(await client.get(destination)).toEqual(value1); - expect(await client.select(index2)).toEqual("OK"); - checkSimple(await client.get(destination)).toEqual(value2); - - // both exists, with REPLACE, when value isn't the same, source always get copied to - // destination - expect(await client.select(index0)).toEqual("OK"); - checkSimple( - await client.copyDB(source, destination, index1, true), - ).toEqual(true); - expect(await client.select(index1)).toEqual("OK"); - checkSimple(await client.get(destination)).toEqual(value2); - } finally { - // switching back to db 0 - await client.select(index0); - } + //transaction tests + const transaction = new Transaction(); + transaction.select(index1); + transaction.set(source, value1); + transaction.copy(source, destination, { + destinationDB: index1, + replace: true, + }); + transaction.get(destination); + const results = await client.exec(transaction); - // transaction tests - try { - const transaction = new Transaction(); - transaction.select(index1); - transaction.set(source, value1); - transaction.copy(source, destination, index1, true); - transaction.get(destination); - const results = await client.exec(transaction); - - if (results != null) { - checkSimple(results.length).toEqual(4); - checkSimple(results[2]).toEqual(true); - checkSimple(results[3]).toEqual(value1); - } - } finally { - // switching back to db 0 - await client.select(index0); - } + checkSimple(results).toEqual(["OK", "OK", true, value1]); client.close(); }, diff --git a/node/tests/RedisClusterClient.test.ts b/node/tests/RedisClusterClient.test.ts index 370abf987c..1486b92476 100644 --- a/node/tests/RedisClusterClient.test.ts +++ b/node/tests/RedisClusterClient.test.ts @@ -325,7 +325,7 @@ describe("GlideClusterClient", () => { client.zdiff(["abc", "zxy", "lkn"]), client.zdiffWithScores(["abc", "zxy", "lkn"]), client.zdiffstore("abc", ["zxy", "lkn"]), - client.copy("abc", "zxy", true), + client.copy("abc", "zxy", { replace: true }), ); } @@ -538,6 +538,62 @@ describe("GlideClusterClient", () => { TIMEOUT, ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + "copy test_%p", + async (protocol) => { + const client = await GlideClusterClient.createClient( + getClientConfigurationOption(cluster.getAddresses(), protocol), + ); + + if (cluster.checkIfServerVersionLessThan("6.2.0")) return; + + const source = `{key}-${uuidv4()}`; + const destination = `{key}-${uuidv4()}`; + const value1 = uuidv4(); + const value2 = uuidv4(); + + // neither key exists + checkSimple( + await client.copy(source, destination, { replace: true }), + ).toEqual(false); + checkSimple(await client.copy(source, destination)).toEqual(false); + + // source exists, destination does not + expect(await client.set(source, value1)).toEqual("OK"); + checkSimple( + await client.copy(source, destination, { replace: false }), + ).toEqual(true); + checkSimple(await client.get(destination)).toEqual(value1); + + // new value for source key + expect(await client.set(source, value2)).toEqual("OK"); + + // both exists, no REPLACE + checkSimple(await client.copy(source, destination)).toEqual(false); + checkSimple( + await client.copy(source, destination, { replace: false }), + ).toEqual(false); + checkSimple(await client.get(destination)).toEqual(value1); + + // both exists, with REPLACE + checkSimple( + await client.copy(source, destination, { replace: true }), + ).toEqual(true); + checkSimple(await client.get(destination)).toEqual(value2); + + //transaction tests + const transaction = new ClusterTransaction(); + transaction.set(source, value1); + transaction.copy(source, destination, { replace: true }); + transaction.get(destination); + const results = await client.exec(transaction); + + checkSimple(results).toEqual(["OK", true, value1]); + + client.close(); + }, + ); + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( "flushdb flushall dbsize test_%p", async (protocol) => { diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index df46c2125d..f96b560a3b 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -4482,54 +4482,6 @@ export function runBaseTests(config: { config.timeout, ); - it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( - "copy test_%p", - async (protocol) => { - await runTest(async (client: BaseClient, cluster: RedisCluster) => { - if (cluster.checkIfServerVersionLessThan("6.2.0")) return; - - const source = `{key}-${uuidv4()}`; - const destination = `{key}-${uuidv4()}`; - const value1 = uuidv4(); - const value2 = uuidv4(); - - // neither key exists - checkSimple( - await client.copy(source, destination, false), - ).toEqual(false); - checkSimple(await client.copy(source, destination)).toEqual( - false, - ); - - // source exists, destination does not - expect(await client.set(source, value1)).toEqual("OK"); - checkSimple( - await client.copy(source, destination, false), - ).toEqual(true); - checkSimple(await client.get(destination)).toEqual(value1); - - // new value for source key - expect(await client.set(source, value2)).toEqual("OK"); - - // both exists, no REPLACE - checkSimple(await client.copy(source, destination)).toEqual( - false, - ); - checkSimple( - await client.copy(source, destination, false), - ).toEqual(false); - checkSimple(await client.get(destination)).toEqual(value1); - - // both exists, with REPLACE - checkSimple( - await client.copy(source, destination, true), - ).toEqual(true); - checkSimple(await client.get(destination)).toEqual(value2); - }, protocol); - }, - config.timeout, - ); - it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( `flushall test_%p`, async (protocol) => { diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 9cdf07b297..68f97c1dba 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -19,8 +19,8 @@ import { GlideClient, GlideClusterClient, InsertPosition, - Logger, ListDirection, + Logger, ProtocolVersion, ReturnType, ScoreFilter, @@ -718,11 +718,6 @@ export async function transactionTest( 1, ]); - if (gte("6.2.0", version)) { - baseTransaction.copy(key9, key10, undefined, true); - responseData.push(["copy(key9, key10, undefined, true)", true]); - } - baseTransaction.rename(key9, key10); responseData.push(["rename(key9, key10)", "OK"]); baseTransaction.exists([key10]); From fbc575bc7380b689cd7ec6e62d9fdf15d449961a Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 11:09:40 -0700 Subject: [PATCH 5/9] Removed unused Logger import Signed-off-by: Yi-Pin Chen --- node/tests/TestUtilities.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 4814b30da3..6ff8c7a8a8 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -21,7 +21,6 @@ import { GlideClusterClient, InsertPosition, ListDirection, - Logger, ProtocolVersion, ReturnType, ScoreFilter, @@ -773,7 +772,6 @@ export async function transactionTest( 'xtrim(key9, { method: "minid", threshold: "0-2", exact: true }', 1, ]); - baseTransaction.rename(key9, key10); responseData.push(["rename(key9, key10)", "OK"]); baseTransaction.exists([key10]); From 5cdae4f037269a38a20489f7adf0cbdb109737ef Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 11:11:28 -0700 Subject: [PATCH 6/9] Removed unused MemberOrigin to fix lint check Signed-off-by: Yi-Pin Chen --- node/src/BaseClient.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index fd55460724..1c14e2c6ff 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -28,7 +28,6 @@ import { KeyWeight, // eslint-disable-line @typescript-eslint/no-unused-vars LPosOptions, ListDirection, - MemberOrigin, RangeByIndex, RangeByLex, RangeByScore, From 927825d4d7c2002981d67e83912ddff391ad07a6 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 11:14:09 -0700 Subject: [PATCH 7/9] Redo MemberOrigin removal Signed-off-by: Yi-Pin Chen --- node/src/BaseClient.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 1c14e2c6ff..bd2e0bde51 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -25,9 +25,10 @@ import { GeoUnit, GeospatialData, InsertPosition, - KeyWeight, // eslint-disable-line @typescript-eslint/no-unused-vars + KeyWeight, LPosOptions, ListDirection, + MemberOrigin, // eslint-disable-line @typescript-eslint/no-unused-vars RangeByIndex, RangeByLex, RangeByScore, From 244c47cdb32482e9a2aa07f33d1e66d6b4ce8888 Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 15:22:48 -0700 Subject: [PATCH 8/9] Addressed review comments Signed-off-by: Yi-Pin Chen --- node/src/GlideClient.ts | 11 ++++++++- node/src/GlideClusterClient.ts | 6 ++--- node/src/Transaction.ts | 17 ++++++++----- node/tests/RedisClient.test.ts | 10 ++++---- node/tests/RedisClientInternals.test.ts | 6 ++--- node/tests/RedisClusterClient.test.ts | 32 ++++++++++++------------- 6 files changed, 48 insertions(+), 34 deletions(-) diff --git a/node/src/GlideClient.ts b/node/src/GlideClient.ts index 47e51fb91b..09af14ed92 100644 --- a/node/src/GlideClient.ts +++ b/node/src/GlideClient.ts @@ -377,7 +377,7 @@ export class GlideClient extends BaseClient { /** * Copies the value stored at the `source` to the `destination` key. If `destinationDB` is specified, - * the value will be copied to the databased specified, otherwise the current database will be used. + * the value will be copied to the database specified, otherwise the current database will be used. * When `replace` is true, removes the `destination` key first if it already exists, otherwise performs * no action. * @@ -386,6 +386,7 @@ export class GlideClient extends BaseClient { * @param source - The key to the source value. * @param destination - The key where the value should be copied to. * @param destinationDB - (Optional) The alternative logical database index for the destination key. + * If not provided, the current database will be used. * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the * value to it. If not provided, no action will be performed if the key already exists. * @returns `true` if `source` was copied, `false` if the `source` was not copied. @@ -394,6 +395,14 @@ export class GlideClient extends BaseClient { * * @example * ```typescript + * const result = await client.copy("set1", "set2"); + * console.log(result); // Output: true - "set1" was copied to "set2". + * ``` + * ```typescript + * const result = await client.copy("set1", "set2", { replace: true }); + * console.log(result); // Output: true - "set1" was copied to "set2". + * ``` + * ```typescript * const result = await client.copy("set1", "set2", { destinationDB: 1, replace: false }); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` diff --git a/node/src/GlideClusterClient.ts b/node/src/GlideClusterClient.ts index 1c451cc0a0..c6b47226f0 100644 --- a/node/src/GlideClusterClient.ts +++ b/node/src/GlideClusterClient.ts @@ -656,17 +656,17 @@ export class GlideClusterClient extends BaseClient { * * @example * ```typescript - * const result = await client.copy("set1", "set2", { replace: true }); + * const result = await client.copy("set1", "set2", true); * console.log(result); // Output: true - "set1" was copied to "set2". * ``` */ public async copy( source: string, destination: string, - options?: { replace?: boolean }, + replace?: boolean, ): Promise { return this.createWritePromise( - createCopy(source, destination, options), + createCopy(source, destination, { replace: replace }), ); } diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index dfc7969500..d68919f4da 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -2392,14 +2392,17 @@ export class Transaction extends BaseTransaction { } /** - * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` - * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * Copies the value stored at the `source` to the `destination` key. If `destinationDB` is specified, + * the value will be copied to the database specified, otherwise the current database will be used. + * When `replace` is true, removes the `destination` key first if it already exists, otherwise performs + * no action. * * See https://valkey.io/commands/copy/ for more details. * * @param source - The key to the source value. * @param destination - The key where the value should be copied to. * @param destinationDB - (Optional) The alternative logical database index for the destination key. + * If not provided, the current database will be used. * @param replace - (Optional) If `true`, the `destination` key should be removed before copying the * value to it. If not provided, no action will be performed if the key already exists. * @@ -2431,8 +2434,8 @@ export class ClusterTransaction extends BaseTransaction { /// TODO: add all CLUSTER commands /** - * Copies the value stored at the `source` to the `destination` key on `destinationDB`. When `replace` - * is true, removes the `destination` key first if it already exists, otherwise performs no action. + * Copies the value stored at the `source` to the `destination` key. When `replace` is true, + * removes the `destination` key first if it already exists, otherwise performs no action. * * See https://valkey.io/commands/copy/ for more details. * @@ -2448,8 +2451,10 @@ export class ClusterTransaction extends BaseTransaction { public copy( source: string, destination: string, - options?: { replace?: boolean }, + replace?: boolean, ): ClusterTransaction { - return this.addAndReturn(createCopy(source, destination, options)); + return this.addAndReturn( + createCopy(source, destination, { replace: replace }), + ); } } diff --git a/node/tests/RedisClient.test.ts b/node/tests/RedisClient.test.ts index f0a7f284e9..dab8ca6edb 100644 --- a/node/tests/RedisClient.test.ts +++ b/node/tests/RedisClient.test.ts @@ -384,7 +384,7 @@ describe("GlideClient", () => { const index2 = 2; // neither key exists - checkSimple( + expect( await client.copy(source, destination, { destinationDB: index1, replace: false, @@ -393,7 +393,7 @@ describe("GlideClient", () => { // source exists, destination does not expect(await client.set(source, value1)).toEqual("OK"); - checkSimple( + expect( await client.copy(source, destination, { destinationDB: index1, replace: false, @@ -407,13 +407,13 @@ describe("GlideClient", () => { expect(await client.set(source, value2)).toEqual("OK"); // no REPLACE, copying to existing key on DB 1, non-existing key on DB 2 - checkSimple( + expect( await client.copy(source, destination, { destinationDB: index1, replace: false, }), ).toEqual(false); - checkSimple( + expect( await client.copy(source, destination, { destinationDB: index2, replace: false, @@ -429,7 +429,7 @@ describe("GlideClient", () => { // both exists, with REPLACE, when value isn't the same, source always get copied to // destination expect(await client.select(index0)).toEqual("OK"); - checkSimple( + expect( await client.copy(source, destination, { destinationDB: index1, replace: true, diff --git a/node/tests/RedisClientInternals.test.ts b/node/tests/RedisClientInternals.test.ts index 888b47c374..631c936513 100644 --- a/node/tests/RedisClientInternals.test.ts +++ b/node/tests/RedisClientInternals.test.ts @@ -22,6 +22,7 @@ import { BaseClientConfiguration, ClosingError, ClusterClientConfiguration, + ClusterTransaction, GlideClient, GlideClientConfiguration, GlideClusterClient, @@ -30,7 +31,6 @@ import { RequestError, ReturnType, SlotKeyTypes, - Transaction, } from ".."; import { command_request, @@ -376,7 +376,7 @@ describe("SocketConnectionInternals", () => { sendResponse(socket, ResponseType.OK, request.callbackIdx); }); - const transaction = new Transaction(); + const transaction = new ClusterTransaction(); transaction.set("key", "value"); const slotKey: SlotKeyTypes = { type: "primarySlotKey", @@ -408,7 +408,7 @@ describe("SocketConnectionInternals", () => { value: "# Server", }); }); - const transaction = new Transaction(); + const transaction = new ClusterTransaction(); transaction.info([InfoOptions.Server]); const result = await connection.exec(transaction, "randomNode"); expect(intoString(result)).toEqual( diff --git a/node/tests/RedisClusterClient.test.ts b/node/tests/RedisClusterClient.test.ts index 728c693778..902ff7896c 100644 --- a/node/tests/RedisClusterClient.test.ts +++ b/node/tests/RedisClusterClient.test.ts @@ -327,7 +327,7 @@ describe("GlideClusterClient", () => { client.zdiff(["abc", "zxy", "lkn"]), client.zdiffWithScores(["abc", "zxy", "lkn"]), client.zdiffstore("abc", ["zxy", "lkn"]), - client.copy("abc", "zxy", { replace: true }), + client.copy("abc", "zxy", true), ); } @@ -555,38 +555,38 @@ describe("GlideClusterClient", () => { const value2 = uuidv4(); // neither key exists - checkSimple( - await client.copy(source, destination, { replace: true }), - ).toEqual(false); - checkSimple(await client.copy(source, destination)).toEqual(false); + expect(await client.copy(source, destination, true)).toEqual( + false, + ); + expect(await client.copy(source, destination)).toEqual(false); // source exists, destination does not expect(await client.set(source, value1)).toEqual("OK"); - checkSimple( - await client.copy(source, destination, { replace: false }), - ).toEqual(true); + expect(await client.copy(source, destination, false)).toEqual( + true, + ); checkSimple(await client.get(destination)).toEqual(value1); // new value for source key expect(await client.set(source, value2)).toEqual("OK"); // both exists, no REPLACE - checkSimple(await client.copy(source, destination)).toEqual(false); - checkSimple( - await client.copy(source, destination, { replace: false }), - ).toEqual(false); + expect(await client.copy(source, destination)).toEqual(false); + expect(await client.copy(source, destination, false)).toEqual( + false, + ); checkSimple(await client.get(destination)).toEqual(value1); // both exists, with REPLACE - checkSimple( - await client.copy(source, destination, { replace: true }), - ).toEqual(true); + expect(await client.copy(source, destination, true)).toEqual( + true, + ); checkSimple(await client.get(destination)).toEqual(value2); //transaction tests const transaction = new ClusterTransaction(); transaction.set(source, value1); - transaction.copy(source, destination, { replace: true }); + transaction.copy(source, destination, true); transaction.get(destination); const results = await client.exec(transaction); From f37d3047ce71a94aeeff1564bff025da72e67f4d Mon Sep 17 00:00:00 2001 From: Yi-Pin Chen Date: Mon, 29 Jul 2024 15:24:56 -0700 Subject: [PATCH 9/9] Fixed lint errors Signed-off-by: Yi-Pin Chen --- node/tests/RedisClusterClient.test.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/node/tests/RedisClusterClient.test.ts b/node/tests/RedisClusterClient.test.ts index 902ff7896c..0f7281746d 100644 --- a/node/tests/RedisClusterClient.test.ts +++ b/node/tests/RedisClusterClient.test.ts @@ -555,16 +555,12 @@ describe("GlideClusterClient", () => { const value2 = uuidv4(); // neither key exists - expect(await client.copy(source, destination, true)).toEqual( - false, - ); + expect(await client.copy(source, destination, true)).toEqual(false); expect(await client.copy(source, destination)).toEqual(false); // source exists, destination does not expect(await client.set(source, value1)).toEqual("OK"); - expect(await client.copy(source, destination, false)).toEqual( - true, - ); + expect(await client.copy(source, destination, false)).toEqual(true); checkSimple(await client.get(destination)).toEqual(value1); // new value for source key @@ -578,9 +574,7 @@ describe("GlideClusterClient", () => { checkSimple(await client.get(destination)).toEqual(value1); // both exists, with REPLACE - expect(await client.copy(source, destination, true)).toEqual( - true, - ); + expect(await client.copy(source, destination, true)).toEqual(true); checkSimple(await client.get(destination)).toEqual(value2); //transaction tests