diff --git a/CHANGELOG.md b/CHANGELOG.md index f0fc01fa5e..9bcf55d700 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,13 +6,15 @@ * Python, Node: Added TYPE command ([#945](https://github.com/aws/glide-for-redis/pull/945), [#980](https://github.com/aws/glide-for-redis/pull/980)) * Python, Node: Added HLEN command ([#944](https://github.com/aws/glide-for-redis/pull/944), [#981](https://github.com/aws/glide-for-redis/pull/981)) * Python, Node: Added ZCOUNT command ([#878](https://github.com/aws/glide-for-redis/pull/878)) ([#909](https://github.com/aws/glide-for-redis/pull/909)) -* Python: Added ECHO command ([#953](https://github.com/aws/glide-for-redis/pull/953)) +* Python, Node: Added ECHO command ([#953](https://github.com/aws/glide-for-redis/pull/953), [#1010](https://github.com/aws/glide-for-redis/pull/1010)) * Python, Node: Added ZPOPMIN command ([#975](https://github.com/aws/glide-for-redis/pull/975), [#1008](https://github.com/aws/glide-for-redis/pull/1008)) * Node: Added STRLEN command ([#993](https://github.com/aws/glide-for-redis/pull/993)) * Node: Added LINDEX command ([#999](https://github.com/aws/glide-for-redis/pull/999)) * Python, Node: Added ZPOPMAX command ([#996](https://github.com/aws/glide-for-redis/pull/996), [#1009](https://github.com/aws/glide-for-redis/pull/1009)) * Python: Added ZRANGE command ([#906](https://github.com/aws/glide-for-redis/pull/906)) * Python, Node: Added PTTL command ([#1036](https://github.com/aws/glide-for-redis/pull/1036), [#1082](https://github.com/aws/glide-for-redis/pull/1082)) +* Node: Added HVAL command ([#1022](https://github.com/aws/glide-for-redis/pull/1022)) +* Node: Added PERSIST command ([#1023](https://github.com/aws/glide-for-redis/pull/1023)) #### Features diff --git a/glide-core/src/client/value_conversion.rs b/glide-core/src/client/value_conversion.rs index 9538791422..21bfb3d4b7 100644 --- a/glide-core/src/client/value_conversion.rs +++ b/glide-core/src/client/value_conversion.rs @@ -200,7 +200,7 @@ pub(crate) fn expected_type_for_cmd(cmd: &Cmd) -> Option { } b"INCRBYFLOAT" | b"HINCRBYFLOAT" => Some(ExpectedReturnType::Double), b"HEXISTS" | b"HSETNX" | b"EXPIRE" | b"EXPIREAT" | b"PEXPIRE" | b"PEXPIREAT" - | b"SISMEMBER" => Some(ExpectedReturnType::Boolean), + | b"SISMEMBER" | b"PERSIST" => Some(ExpectedReturnType::Boolean), b"SMEMBERS" => Some(ExpectedReturnType::Set), b"ZSCORE" => Some(ExpectedReturnType::DoubleOrNull), b"ZPOPMIN" | b"ZPOPMAX" => Some(ExpectedReturnType::MapOfStringToDouble), diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto index 877c773b8d..586e8b2e16 100644 --- a/glide-core/src/protobuf/redis_request.proto +++ b/glide-core/src/protobuf/redis_request.proto @@ -128,6 +128,7 @@ enum RequestType { Hvals = 84; PTTL = 85; ZRemRangeByRank = 86; + Persist = 87; } message Command { diff --git a/glide-core/src/socket_listener.rs b/glide-core/src/socket_listener.rs index 89a289acc2..5760cd3ca7 100644 --- a/glide-core/src/socket_listener.rs +++ b/glide-core/src/socket_listener.rs @@ -358,6 +358,7 @@ fn get_command(request: &Command) -> Option { RequestType::Hvals => Some(cmd("HVALS")), RequestType::PTTL => Some(cmd("PTTL")), RequestType::ZRemRangeByRank => Some(cmd("ZREMRANGEBYRANK")), + RequestType::Persist => Some(cmd("PERSIST")), } } diff --git a/node/src/BaseClient.ts b/node/src/BaseClient.ts index 198fc408e0..ae9363b0d2 100644 --- a/node/src/BaseClient.ts +++ b/node/src/BaseClient.ts @@ -47,6 +47,7 @@ import { createMSet, createPExpire, createPExpireAt, + createPersist, createPttl, createRPop, createRPush, @@ -1176,7 +1177,7 @@ export class BaseClient { * Both `start` and `end` are zero-based indexes with 0 being the element with the lowest score. * These indexes can be negative numbers, where they indicate offsets starting at the element with the highest score. * See https://redis.io/commands/zremrangebyrank/ for more details. - * + * * @param key - The key of the sorted set. * @param start - The starting point of the range. * @param end - The end of the range. @@ -1185,7 +1186,11 @@ export class BaseClient { * If `end` exceeds the actual end of the sorted set, the range will stop at the actual end of the sorted set. * If `key` does not exist 0 will be returned. */ - public zremRangeByRank(key: string, start: number, end: number): Promise { + public zremRangeByRank( + key: string, + start: number, + end: number, + ): Promise { return this.createWritePromise(createZremRangeByRank(key, start, end)); } @@ -1212,6 +1217,17 @@ export class BaseClient { return this.createWritePromise(createLindex(key, index)); } + /** Remove the existing timeout on `key`, turning the key from volatile (a key with an expire set) to + * persistent (a key that will never expire as no timeout is associated). + * See https://redis.io/commands/persist/ for more details. + * + * @param key - The key to remove the existing timeout on. + * @returns `false` if `key` does not exist or does not have an associated timeout, `true` if the timeout has been removed. + */ + public persist(key: string): Promise { + return this.createWritePromise(createPersist(key)); + } + /** * @internal */ diff --git a/node/src/Commands.ts b/node/src/Commands.ts index c7edf68aec..15e2cd50df 100644 --- a/node/src/Commands.ts +++ b/node/src/Commands.ts @@ -897,7 +897,7 @@ export function createPttl(key: string): redis_request.Command { export function createZremRangeByRank( key: string, start: number, - stop: number + stop: number, ): redis_request.Command { return createCommand(RequestType.ZRemRangeByRank, [ key, @@ -905,3 +905,10 @@ export function createZremRangeByRank( stop.toString(), ]); } + +/** + * @internal + */ +export function createPersist(key: string): redis_request.Command { + return createCommand(RequestType.Persist, [key]); +} diff --git a/node/src/Transaction.ts b/node/src/Transaction.ts index b6bc409e89..f343b9bee1 100644 --- a/node/src/Transaction.ts +++ b/node/src/Transaction.ts @@ -48,6 +48,7 @@ import { createMSet, createPExpire, createPExpireAt, + createPersist, createPing, createPttl, createRPop, @@ -941,11 +942,11 @@ export class BaseTransaction> { * Both `start` and `end` are zero-based indexes with 0 being the element with the lowest score. * These indexes can be negative numbers, where they indicate offsets starting at the element with the highest score. * See https://redis.io/commands/zremrangebyrank/ for more details. - * + * * @param key - The key of the sorted set. * @param start - The starting point of the range. * @param end - The end of the range. - * + * * Command Response - The number of members removed. * If `start` exceeds the end of the sorted set, or if `start` is greater than `end`, 0 returned. * If `end` exceeds the actual end of the sorted set, the range will stop at the actual end of the sorted set. @@ -955,6 +956,18 @@ export class BaseTransaction> { return this.addAndReturn(createZremRangeByRank(key, start, end)); } + /** Remove the existing timeout on `key`, turning the key from volatile (a key with an expire set) to + * persistent (a key that will never expire as no timeout is associated). + * See https://redis.io/commands/persist/ for more details. + * + * @param key - The key to remove the existing timeout on. + * + * Command Response - `false` if `key` does not exist or does not have an associated timeout, `true` if the timeout has been removed. + */ + public persist(key: string): T { + return this.addAndReturn(createPersist(key)); + } + /** Executes a single command, without checking inputs. Every part of the command, including subcommands, * should be added as a separate value in args. * diff --git a/node/tests/SharedTests.ts b/node/tests/SharedTests.ts index d1241ec438..63ee8d6503 100644 --- a/node/tests/SharedTests.ts +++ b/node/tests/SharedTests.ts @@ -1705,11 +1705,26 @@ export function runBaseTests(config: { expect(await client.zremRangeByRank(key, 0, 1)).toEqual(2); expect(await client.zremRangeByRank(key, 0, 10)).toEqual(1); expect( - await client.zremRangeByRank("nonExistingKey", 0, -1) + await client.zremRangeByRank("nonExistingKey", 0, -1), ).toEqual(0); }, protocol); }, - config.timeout + config.timeout, + ); + + it.each([ProtocolVersion.RESP2, ProtocolVersion.RESP3])( + `persist test_%p`, + async (protocol) => { + await runTest(async (client: BaseClient) => { + const key = uuidv4(); + expect(await client.set(key, "foo")).toEqual("OK"); + expect(await client.persist(key)).toEqual(false); + + expect(await client.expire(key, 10)).toEqual(true); + expect(await client.persist(key)).toEqual(true); + }, protocol); + }, + config.timeout, ); } diff --git a/node/tests/TestUtilities.ts b/node/tests/TestUtilities.ts index 7614cb26ca..43340a462b 100644 --- a/node/tests/TestUtilities.ts +++ b/node/tests/TestUtilities.ts @@ -70,6 +70,8 @@ export function transactionTest( args.push("string"); baseTransaction.echo(value); args.push(value); + baseTransaction.persist(key1); + args.push(false); baseTransaction.set(key2, "baz", { returnOldValue: true, }); @@ -135,7 +137,12 @@ export function transactionTest( args.push(1); baseTransaction.smembers(key7); args.push(["bar"]); - baseTransaction.zadd(key8, { member1: 1, member2: 2, member3: 3.5, member4: 4 }); + baseTransaction.zadd(key8, { + member1: 1, + member2: 2, + member3: 3.5, + member4: 4, + }); args.push(4); baseTransaction.zaddIncr(key8, "member2", 1); args.push(3);