From bfa803fa55e336301eceaa25ded9f19cb9678b6b Mon Sep 17 00:00:00 2001 From: jjsimps <98552694+jjsimps@users.noreply.github.com> Date: Thu, 16 May 2024 12:17:32 -0500 Subject: [PATCH 01/31] Fix race condition when slots are re-calculated (#2731) --- packages/client/lib/cluster/cluster-slots.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index b1cc49b4c82..489ded4854f 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -158,13 +158,13 @@ export default class RedisClusterSlots< } async #discover(rootNode?: RedisClusterClientOptions) { - this.#resetSlots(); const addressesInUse = new Set(); try { const shards = await this.#getShards(rootNode), promises: Array> = [], eagerConnect = this.#options.minimizeConnections !== true; + this.#resetSlots(); for (const { from, to, master, replicas } of shards) { const shard: Shard = { master: this.#initiateSlotNode(master, false, eagerConnect, addressesInUse, promises) From d7f7f79e538759366cd733fa0cb978684e5c1305 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 16 May 2024 13:53:52 -0400 Subject: [PATCH 02/31] Release client@1.5.15 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 839ce6d8b66..4e6fce3ed9d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.14", + "version": "1.5.15", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 1a3ac1e0970e0e53a2e8d4f8884dde30fe028300 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 16 May 2024 13:56:30 -0400 Subject: [PATCH 03/31] upgrade @redis/client --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5cae28a971f..e45d5dcbf1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.14", + "@redis/client": "1.5.15", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -8838,7 +8838,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "1.5.14", + "version": "1.5.15", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", diff --git a/package.json b/package.json index 07e1f13484d..cde019ed0d3 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.14", + "@redis/client": "1.5.15", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", From d5518e0b5f8a0b2705ff5174f518a9522dd0f9dd Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 16 May 2024 14:01:01 -0400 Subject: [PATCH 04/31] Release client@1.5.16 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 4e6fce3ed9d..26f0c0e649c 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.15", + "version": "1.5.16", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From fcf41192d159b54a619f39f2379133bbe25d4c36 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 16 May 2024 14:03:30 -0400 Subject: [PATCH 05/31] upgrade @redis/client --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e45d5dcbf1b..a0398526f58 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.15", + "@redis/client": "1.5.16", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -8838,7 +8838,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "1.5.15", + "version": "1.5.16", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", diff --git a/package.json b/package.json index cde019ed0d3..79ff2afd330 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.15", + "@redis/client": "1.5.16", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", From d5355d43275fedf1b2afc4db8a926f72b05f79c5 Mon Sep 17 00:00:00 2001 From: Leibale Date: Thu, 16 May 2024 14:05:01 -0400 Subject: [PATCH 06/31] Release redis@4.6.14 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index a0398526f58..9f977d2c99d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "redis", - "version": "4.6.13", + "version": "4.6.14", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "redis", - "version": "4.6.13", + "version": "4.6.14", "license": "MIT", "workspaces": [ "./packages/*" diff --git a/package.json b/package.json index 79ff2afd330..f42208c55a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "4.6.13", + "version": "4.6.14", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 4ac97eeaacceb7f0710e10bb020f8793b37cf820 Mon Sep 17 00:00:00 2001 From: Max Gruenfelder Date: Tue, 2 Jul 2024 18:00:27 +0200 Subject: [PATCH 07/31] fix createCluster - copy `options.defaults.socket` before modifying it (#2783) * shallow copy of this.#options.defaults.socket * shallow copy of this.#options.defaults.socket * nit --------- Co-authored-by: Max Gruenfelder Co-authored-by: Leibale Eidelman --- packages/client/lib/cluster/cluster-slots.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/client/lib/cluster/cluster-slots.ts b/packages/client/lib/cluster/cluster-slots.ts index 489ded4854f..45c96a80b50 100644 --- a/packages/client/lib/cluster/cluster-slots.ts +++ b/packages/client/lib/cluster/cluster-slots.ts @@ -269,10 +269,10 @@ export default class RedisClusterSlots< if (this.#options.defaults) { let socket; if (this.#options.defaults.socket) { - socket = options?.socket ? { + socket = { ...this.#options.defaults.socket, - ...options.socket - } : this.#options.defaults.socket; + ...options?.socket + }; } else { socket = options?.socket; } From 60c1c466babd1249e50df5a7fd9289b89348dc6e Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 2 Jul 2024 13:37:23 -0400 Subject: [PATCH 08/31] Release client@1.5.17 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 26f0c0e649c..026e4261786 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.16", + "version": "1.5.17", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From b4c1e59fc9db83902889e5a88e3917c7102b32e4 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 2 Jul 2024 13:38:04 -0400 Subject: [PATCH 09/31] Upgrade @redis/client --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9f977d2c99d..dc869d8ddbf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.16", + "@redis/client": "1.5.17", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", @@ -8838,7 +8838,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "1.5.16", + "version": "1.5.17", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", diff --git a/package.json b/package.json index f42208c55a8..37b307fbac8 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.16", + "@redis/client": "1.5.17", "@redis/graph": "1.1.1", "@redis/json": "1.0.6", "@redis/search": "1.1.6", From 72345fe1a2227bd726a242f31211ed2596705258 Mon Sep 17 00:00:00 2001 From: Leibale Date: Tue, 2 Jul 2024 13:38:40 -0400 Subject: [PATCH 10/31] Release redis@4.6.15 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index dc869d8ddbf..11ae2a61088 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "redis", - "version": "4.6.14", + "version": "4.6.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "redis", - "version": "4.6.14", + "version": "4.6.15", "license": "MIT", "workspaces": [ "./packages/*" diff --git a/package.json b/package.json index 37b307fbac8..586ef8b8dad 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "4.6.14", + "version": "4.6.15", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From b4df2b24a82ab9aae30d81572417810c3145e977 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 10 Jul 2024 19:44:30 +0300 Subject: [PATCH 11/31] add support for all hash field expiration commands (#2787) --- packages/client/lib/cluster/commands.ts | 27 ++++++++++ packages/client/lib/commands/HEXPIRE.spec.ts | 40 +++++++++++++++ packages/client/lib/commands/HEXPIRE.ts | 44 +++++++++++++++++ .../client/lib/commands/HEXPIREAT.spec.ts | 49 +++++++++++++++++++ packages/client/lib/commands/HEXPIREAT.ts | 28 +++++++++++ .../client/lib/commands/HEXPIRETIME.spec.ts | 32 ++++++++++++ packages/client/lib/commands/HEXPIRETIME.ts | 21 ++++++++ packages/client/lib/commands/HPERSIST.spec.ts | 33 +++++++++++++ packages/client/lib/commands/HPERSIST.ts | 10 ++++ packages/client/lib/commands/HPEXPIRE.spec.ts | 40 +++++++++++++++ packages/client/lib/commands/HPEXPIRE.ts | 24 +++++++++ .../client/lib/commands/HPEXPIREAT.spec.ts | 48 ++++++++++++++++++ packages/client/lib/commands/HPEXPIREAT.ts | 25 ++++++++++ .../client/lib/commands/HPEXPIRETIME.spec.ts | 33 +++++++++++++ packages/client/lib/commands/HPEXPIRETIME.ts | 11 +++++ packages/client/lib/commands/HPTTL.spec.ts | 33 +++++++++++++ packages/client/lib/commands/HPTTL.ts | 11 +++++ packages/client/lib/commands/HTTL.spec.ts | 34 +++++++++++++ packages/client/lib/commands/HTTL.ts | 11 +++++ packages/client/lib/test-utils.ts | 2 +- 20 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 packages/client/lib/commands/HEXPIRE.spec.ts create mode 100644 packages/client/lib/commands/HEXPIRE.ts create mode 100644 packages/client/lib/commands/HEXPIREAT.spec.ts create mode 100644 packages/client/lib/commands/HEXPIREAT.ts create mode 100644 packages/client/lib/commands/HEXPIRETIME.spec.ts create mode 100644 packages/client/lib/commands/HEXPIRETIME.ts create mode 100644 packages/client/lib/commands/HPERSIST.spec.ts create mode 100644 packages/client/lib/commands/HPERSIST.ts create mode 100644 packages/client/lib/commands/HPEXPIRE.spec.ts create mode 100644 packages/client/lib/commands/HPEXPIRE.ts create mode 100644 packages/client/lib/commands/HPEXPIREAT.spec.ts create mode 100644 packages/client/lib/commands/HPEXPIREAT.ts create mode 100644 packages/client/lib/commands/HPEXPIRETIME.spec.ts create mode 100644 packages/client/lib/commands/HPEXPIRETIME.ts create mode 100644 packages/client/lib/commands/HPTTL.spec.ts create mode 100644 packages/client/lib/commands/HPTTL.ts create mode 100644 packages/client/lib/commands/HTTL.spec.ts create mode 100644 packages/client/lib/commands/HTTL.ts diff --git a/packages/client/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts index 84a37862772..b6913b40686 100644 --- a/packages/client/lib/cluster/commands.ts +++ b/packages/client/lib/cluster/commands.ts @@ -53,6 +53,9 @@ import * as GETRANGE from '../commands/GETRANGE'; import * as GETSET from '../commands/GETSET'; import * as HDEL from '../commands/HDEL'; import * as HEXISTS from '../commands/HEXISTS'; +import * as HEXPIRE from '../commands/HEXPIRE'; +import * as HEXPIREAT from '../commands/HEXPIREAT'; +import * as HEXPIRETIME from '../commands/HEXPIRETIME'; import * as HGET from '../commands/HGET'; import * as HGETALL from '../commands/HGETALL'; import * as HINCRBY from '../commands/HINCRBY'; @@ -60,6 +63,11 @@ import * as HINCRBYFLOAT from '../commands/HINCRBYFLOAT'; import * as HKEYS from '../commands/HKEYS'; import * as HLEN from '../commands/HLEN'; import * as HMGET from '../commands/HMGET'; +import * as HPERSIST from '../commands/HPERSIST'; +import * as HPEXPIRE from '../commands/HPEXPIRE'; +import * as HPEXPIREAT from '../commands/HPEXPIREAT'; +import * as HPEXPIRETIME from '../commands/HPEXPIRETIME'; +import * as HPTTL from '../commands/HPTTL'; import * as HRANDFIELD_COUNT_WITHVALUES from '../commands/HRANDFIELD_COUNT_WITHVALUES'; import * as HRANDFIELD_COUNT from '../commands/HRANDFIELD_COUNT'; import * as HRANDFIELD from '../commands/HRANDFIELD'; @@ -67,6 +75,7 @@ import * as HSCAN from '../commands/HSCAN'; import * as HSET from '../commands/HSET'; import * as HSETNX from '../commands/HSETNX'; import * as HSTRLEN from '../commands/HSTRLEN'; +import * as HTTL from '../commands/HTTL'; import * as HVALS from '../commands/HVALS'; import * as INCR from '../commands/INCR'; import * as INCRBY from '../commands/INCRBY'; @@ -321,6 +330,12 @@ export default { hDel: HDEL, HEXISTS, hExists: HEXISTS, + HEXPIRE, + hExpire: HEXPIRE, + HEXPIREAT, + hExpireAt: HEXPIREAT, + HEXPIRETIME, + hExpireTime: HEXPIRETIME, HGET, hGet: HGET, HGETALL, @@ -335,6 +350,16 @@ export default { hLen: HLEN, HMGET, hmGet: HMGET, + HPERSIST, + hPersist: HPERSIST, + HPEXPIRE, + hpExpire: HPEXPIRE, + HPEXPIREAT, + hpExpireAt: HPEXPIREAT, + HPEXPIRETIME, + hpExpireTime: HPEXPIRETIME, + HPTTL, + hpTTL: HPTTL, HRANDFIELD_COUNT_WITHVALUES, hRandFieldCountWithValues: HRANDFIELD_COUNT_WITHVALUES, HRANDFIELD_COUNT, @@ -349,6 +374,8 @@ export default { hSetNX: HSETNX, HSTRLEN, hStrLen: HSTRLEN, + HTTL, + hTTL: HTTL, HVALS, hVals: HVALS, INCR, diff --git a/packages/client/lib/commands/HEXPIRE.spec.ts b/packages/client/lib/commands/HEXPIRE.spec.ts new file mode 100644 index 00000000000..40f841b3af8 --- /dev/null +++ b/packages/client/lib/commands/HEXPIRE.spec.ts @@ -0,0 +1,40 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HEXPIRE'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HEXPIRE', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field', 1), + ['HEXPIRE', 'key', '1', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2'], 1), + ['HEXPIRE', 'key', '1', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + + it('with set option', () => { + assert.deepEqual( + transformArguments('key', ['field1'], 1, 'NX'), + ['HEXPIRE', 'key', '1', 'NX', 'FIELDS', '1', 'field1'] + ); + }); + }); + + testUtils.testWithClient('hexpire', async client => { + assert.deepEqual( + await client.hExpire('key', ['field1'], 0), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/HEXPIRE.ts b/packages/client/lib/commands/HEXPIRE.ts new file mode 100644 index 00000000000..032790c40bb --- /dev/null +++ b/packages/client/lib/commands/HEXPIRE.ts @@ -0,0 +1,44 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +/** + * @readonly + * @enum {number} + */ +export const HASH_EXPIRATION = { + /** @property {number} */ + /** The field does not exist */ + FieldNotExists: -2, + /** @property {number} */ + /** Specified NX | XX | GT | LT condition not met */ + ConditionNotMet: 0, + /** @property {number} */ + /** Expiration time was set or updated */ + Updated: 1, + /** @property {number} */ + /** Field deleted because the specified expiration time is in the past */ + Deleted: 2 +} as const; + +export type HashExpiration = typeof HASH_EXPIRATION[keyof typeof HASH_EXPIRATION]; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + key: RedisCommandArgument, + fields: RedisCommandArgument| Array, + seconds: number, + mode?: 'NX' | 'XX' | 'GT' | 'LT', +) { + const args = ['HEXPIRE', key, seconds.toString()]; + + if (mode) { + args.push(mode); + } + + args.push('FIELDS'); + + return pushVerdictArgument(args, fields); +} + +export declare function transformReply(): Array; \ No newline at end of file diff --git a/packages/client/lib/commands/HEXPIREAT.spec.ts b/packages/client/lib/commands/HEXPIREAT.spec.ts new file mode 100644 index 00000000000..2ab969eb02e --- /dev/null +++ b/packages/client/lib/commands/HEXPIREAT.spec.ts @@ -0,0 +1,49 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HEXPIREAT'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HEXPIREAT', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string + number', () => { + assert.deepEqual( + transformArguments('key', 'field', 1), + ['HEXPIREAT', 'key', '1', 'FIELDS', '1', 'field'] + ); + }); + + it('array + number', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2'], 1), + ['HEXPIREAT', 'key', '1', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + + it('date', () => { + const d = new Date(); + + assert.deepEqual( + transformArguments('key', ['field1'], d), + ['HEXPIREAT', 'key', Math.floor(d.getTime() / 1000).toString(), 'FIELDS', '1', 'field1'] + ); + }); + + it('with set option', () => { + assert.deepEqual( + transformArguments('key', 'field1', 1, 'GT'), + ['HEXPIREAT', 'key', '1', 'GT', 'FIELDS', '1', 'field1'] + ); + }); + }); + + testUtils.testWithClient('expireAt', async client => { + assert.deepEqual( + await client.hExpireAt('key', 'field1', 1), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + }); +}); diff --git a/packages/client/lib/commands/HEXPIREAT.ts b/packages/client/lib/commands/HEXPIREAT.ts new file mode 100644 index 00000000000..58c52d3a1f6 --- /dev/null +++ b/packages/client/lib/commands/HEXPIREAT.ts @@ -0,0 +1,28 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument, transformEXAT } from './generic-transformers'; +import { HashExpiration } from './HEXPIRE'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + key: RedisCommandArgument, + fields: RedisCommandArgument | Array, + timestamp: number | Date, + mode?: 'NX' | 'XX' | 'GT' | 'LT' +) { + const args = [ + 'HEXPIREAT', + key, + transformEXAT(timestamp) + ]; + + if (mode) { + args.push(mode); + } + + args.push('FIELDS') + + return pushVerdictArgument(args, fields); +} + +export declare function transformReply(): Array; \ No newline at end of file diff --git a/packages/client/lib/commands/HEXPIRETIME.spec.ts b/packages/client/lib/commands/HEXPIRETIME.spec.ts new file mode 100644 index 00000000000..4e5ab82a7e9 --- /dev/null +++ b/packages/client/lib/commands/HEXPIRETIME.spec.ts @@ -0,0 +1,32 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { HASH_EXPIRATION_TIME, transformArguments } from './HEXPIRETIME'; + +describe('HEXPIRETIME', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field'), + ['HEXPIRETIME', 'key', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2']), + ['HEXPIRETIME', 'key', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + }) + + testUtils.testWithClient('hExpireTime', async client => { + assert.deepEqual( + await client.hExpireTime('key', 'field1'), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + }); +}); diff --git a/packages/client/lib/commands/HEXPIRETIME.ts b/packages/client/lib/commands/HEXPIRETIME.ts new file mode 100644 index 00000000000..55ae577f9d0 --- /dev/null +++ b/packages/client/lib/commands/HEXPIRETIME.ts @@ -0,0 +1,21 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +export const HASH_EXPIRATION_TIME = { + /** @property {number} */ + /** The field does not exist */ + FieldNotExists: -2, + /** @property {number} */ + /** The field exists but has no associated expire */ + NoExpiration: -1, +} as const; + +export const FIRST_KEY_INDEX = 1 + +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument, fields: RedisCommandArgument | Array) { + return pushVerdictArgument(['HEXPIRETIME', key, 'FIELDS'], fields); +} + +export declare function transformReply(): Array; \ No newline at end of file diff --git a/packages/client/lib/commands/HPERSIST.spec.ts b/packages/client/lib/commands/HPERSIST.spec.ts new file mode 100644 index 00000000000..594dc30cf74 --- /dev/null +++ b/packages/client/lib/commands/HPERSIST.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HPERSIST'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HPERSIST', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field'), + ['HPERSIST', 'key', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2']), + ['HPERSIST', 'key', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + }) + + testUtils.testWithClient('hPersist', async client => { + assert.deepEqual( + await client.hPersist('key', 'field1'), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + }); +}); diff --git a/packages/client/lib/commands/HPERSIST.ts b/packages/client/lib/commands/HPERSIST.ts new file mode 100644 index 00000000000..862a7548ac1 --- /dev/null +++ b/packages/client/lib/commands/HPERSIST.ts @@ -0,0 +1,10 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: RedisCommandArgument, fields: RedisCommandArgument | Array) { + return pushVerdictArgument(['HPERSIST', key, 'FIELDS'], fields); +} + +export declare function transformReply(): Array | null; \ No newline at end of file diff --git a/packages/client/lib/commands/HPEXPIRE.spec.ts b/packages/client/lib/commands/HPEXPIRE.spec.ts new file mode 100644 index 00000000000..fd11ea359cf --- /dev/null +++ b/packages/client/lib/commands/HPEXPIRE.spec.ts @@ -0,0 +1,40 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HPEXPIRE'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HEXPIRE', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field', 1), + ['HPEXPIRE', 'key', '1', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2'], 1), + ['HPEXPIRE', 'key', '1', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + + it('with set option', () => { + assert.deepEqual( + transformArguments('key', ['field1'], 1, 'NX'), + ['HPEXPIRE', 'key', '1', 'NX', 'FIELDS', '1', 'field1'] + ); + }); + }); + + testUtils.testWithClient('hexpire', async client => { + assert.deepEqual( + await client.hpExpire('key', ['field1'], 0), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/HPEXPIRE.ts b/packages/client/lib/commands/HPEXPIRE.ts new file mode 100644 index 00000000000..afbb056ed4e --- /dev/null +++ b/packages/client/lib/commands/HPEXPIRE.ts @@ -0,0 +1,24 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; +import { HashExpiration } from "./HEXPIRE"; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + key: RedisCommandArgument, + fields: RedisCommandArgument | Array, + ms: number, + mode?: 'NX' | 'XX' | 'GT' | 'LT', +) { + const args = ['HPEXPIRE', key, ms.toString()]; + + if (mode) { + args.push(mode); + } + + args.push('FIELDS') + + return pushVerdictArgument(args, fields); +} + +export declare function transformReply(): Array | null; \ No newline at end of file diff --git a/packages/client/lib/commands/HPEXPIREAT.spec.ts b/packages/client/lib/commands/HPEXPIREAT.spec.ts new file mode 100644 index 00000000000..abe49f1d8d7 --- /dev/null +++ b/packages/client/lib/commands/HPEXPIREAT.spec.ts @@ -0,0 +1,48 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HPEXPIREAT'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HPEXPIREAT', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string + number', () => { + assert.deepEqual( + transformArguments('key', 'field', 1), + ['HPEXPIREAT', 'key', '1', 'FIELDS', '1', 'field'] + ); + }); + + it('array + number', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2'], 1), + ['HPEXPIREAT', 'key', '1', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + + it('date', () => { + const d = new Date(); + assert.deepEqual( + transformArguments('key', ['field1'], d), + ['HPEXPIREAT', 'key', d.getTime().toString(), 'FIELDS', '1', 'field1'] + ); + }); + + it('with set option', () => { + assert.deepEqual( + transformArguments('key', ['field1'], 1, 'XX'), + ['HPEXPIREAT', 'key', '1', 'XX', 'FIELDS', '1', 'field1'] + ); + }); + }); + + testUtils.testWithClient('hpExpireAt', async client => { + assert.deepEqual( + await client.hpExpireAt('key', ['field1'], 1), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN, + }); +}); diff --git a/packages/client/lib/commands/HPEXPIREAT.ts b/packages/client/lib/commands/HPEXPIREAT.ts new file mode 100644 index 00000000000..b6e01d8ee5c --- /dev/null +++ b/packages/client/lib/commands/HPEXPIREAT.ts @@ -0,0 +1,25 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument, transformEXAT, transformPXAT } from './generic-transformers'; +import { HashExpiration } from './HEXPIRE'; + +export const FIRST_KEY_INDEX = 1; +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + fields: RedisCommandArgument | Array, + timestamp: number | Date, + mode?: 'NX' | 'XX' | 'GT' | 'LT' +) { + const args = ['HPEXPIREAT', key, transformPXAT(timestamp)]; + + if (mode) { + args.push(mode); + } + + args.push('FIELDS') + + return pushVerdictArgument(args, fields); +} + +export declare function transformReply(): Array | null; \ No newline at end of file diff --git a/packages/client/lib/commands/HPEXPIRETIME.spec.ts b/packages/client/lib/commands/HPEXPIRETIME.spec.ts new file mode 100644 index 00000000000..afaa46a7793 --- /dev/null +++ b/packages/client/lib/commands/HPEXPIRETIME.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HPEXPIRETIME'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HPEXPIRETIME', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field'), + ['HPEXPIRETIME', 'key', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2']), + ['HPEXPIRETIME', 'key', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + }); + + testUtils.testWithClient('hpExpireTime', async client => { + assert.deepEqual( + await client.hpExpireTime('key', 'field1'), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/HPEXPIRETIME.ts b/packages/client/lib/commands/HPEXPIRETIME.ts new file mode 100644 index 00000000000..22a794ccefa --- /dev/null +++ b/packages/client/lib/commands/HPEXPIRETIME.ts @@ -0,0 +1,11 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 1; +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument, fields: RedisCommandArgument | Array) { + return pushVerdictArgument(['HPEXPIRETIME', key, 'FIELDS'], fields); +} + +export declare function transformReply(): Array | null; \ No newline at end of file diff --git a/packages/client/lib/commands/HPTTL.spec.ts b/packages/client/lib/commands/HPTTL.spec.ts new file mode 100644 index 00000000000..0bf10c860e0 --- /dev/null +++ b/packages/client/lib/commands/HPTTL.spec.ts @@ -0,0 +1,33 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HPTTL'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HPTTL', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field'), + ['HPTTL', 'key', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2']), + ['HPTTL', 'key', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + }); + + testUtils.testWithClient('hpTTL', async client => { + assert.deepEqual( + await client.hpTTL('key', 'field1'), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/HPTTL.ts b/packages/client/lib/commands/HPTTL.ts new file mode 100644 index 00000000000..988b805c0c9 --- /dev/null +++ b/packages/client/lib/commands/HPTTL.ts @@ -0,0 +1,11 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 1; +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument, fields: RedisCommandArgument | Array) { + return pushVerdictArgument(['HPTTL', key, 'FIELDS'], fields); +} + +export declare function transformReply(): Array | null; diff --git a/packages/client/lib/commands/HTTL.spec.ts b/packages/client/lib/commands/HTTL.spec.ts new file mode 100644 index 00000000000..a36c681299e --- /dev/null +++ b/packages/client/lib/commands/HTTL.spec.ts @@ -0,0 +1,34 @@ +import { strict as assert } from 'node:assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments } from './HTTL'; +import { HASH_EXPIRATION_TIME } from './HEXPIRETIME'; + +describe('HTTL', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('string', () => { + assert.deepEqual( + transformArguments('key', 'field'), + ['HTTL', 'key', 'FIELDS', '1', 'field'] + ); + }); + + it('array', () => { + assert.deepEqual( + transformArguments('key', ['field1', 'field2']), + ['HTTL', 'key', 'FIELDS', '2', 'field1', 'field2'] + ); + }); + + }); + + testUtils.testWithClient('hTTL', async client => { + assert.deepEqual( + await client.hTTL('key', 'field1'), + [ HASH_EXPIRATION_TIME.FieldNotExists ] + ); + }, { + ...GLOBAL.SERVERS.OPEN + }); +}); diff --git a/packages/client/lib/commands/HTTL.ts b/packages/client/lib/commands/HTTL.ts new file mode 100644 index 00000000000..d3eedd0db0e --- /dev/null +++ b/packages/client/lib/commands/HTTL.ts @@ -0,0 +1,11 @@ +import { RedisCommandArgument } from '.'; +import { pushVerdictArgument } from './generic-transformers'; + +export const FIRST_KEY_INDEX = 1; +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument, fields: RedisCommandArgument | Array) { + return pushVerdictArgument(['HTTL', key, 'FIELDS'], fields); +} + +export declare function transformReply(): Array | null; diff --git a/packages/client/lib/test-utils.ts b/packages/client/lib/test-utils.ts index a9db70c860f..fbbac3e0b71 100644 --- a/packages/client/lib/test-utils.ts +++ b/packages/client/lib/test-utils.ts @@ -5,7 +5,7 @@ import { promiseTimeout } from './utils'; const utils = new TestUtils({ dockerImageName: 'redis', dockerImageVersionArgument: 'redis-version', - defaultDockerVersion: '7.2' + defaultDockerVersion: '7.4-rc2' }); export default utils; From 7d43a97bc7de62d8eefcb4b552d75d1e10d7e7c1 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 10 Jul 2024 19:45:06 +0300 Subject: [PATCH 12/31] add CLIENT KILL maxAge support (v4) (#2761) --- packages/client/lib/commands/CLIENT_KILL.spec.ts | 10 ++++++++++ packages/client/lib/commands/CLIENT_KILL.ts | 13 +++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/CLIENT_KILL.spec.ts b/packages/client/lib/commands/CLIENT_KILL.spec.ts index 2fe894f3610..733aaca858b 100644 --- a/packages/client/lib/commands/CLIENT_KILL.spec.ts +++ b/packages/client/lib/commands/CLIENT_KILL.spec.ts @@ -65,6 +65,16 @@ describe('CLIENT KILL', () => { ); }); + it('MAXAGE', () => { + assert.deepEqual( + transformArguments({ + filter: ClientKillFilters.MAXAGE, + maxAge: 10 + }), + ['CLIENT', 'KILL', 'MAXAGE', '10'] + ); + }); + describe('SKIP_ME', () => { it('undefined', () => { assert.deepEqual( diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index adb2a5a6569..f0b31e5cac0 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -6,7 +6,8 @@ export enum ClientKillFilters { ID = 'ID', TYPE = 'TYPE', USER = 'USER', - SKIP_ME = 'SKIPME' + SKIP_ME = 'SKIPME', + MAXAGE = 'MAXAGE' } interface KillFilter { @@ -37,7 +38,11 @@ type KillSkipMe = ClientKillFilters.SKIP_ME | (KillFilter { + maxAge: number; +} + +type KillFilters = KillAddress | KillLocalAddress | KillId | KillType | KillUser | KillSkipMe | KillMaxage; export function transformArguments(filters: KillFilters | Array): RedisCommandArguments { const args = ['CLIENT', 'KILL']; @@ -89,6 +94,10 @@ function pushFilter(args: RedisCommandArguments, filter: KillFilters): void { case ClientKillFilters.SKIP_ME: args.push(filter.skipMe ? 'yes' : 'no'); break; + + case ClientKillFilters.MAXAGE: + args.push(filter.maxAge.toString()); + break; } } From a1bee1caaf39f98dc3ff99821d111597bfdbe707 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 10 Jul 2024 19:45:17 +0300 Subject: [PATCH 13/31] add geoshape support (#2788) copied from what leibele did for v5 --- packages/search/lib/commands/CREATE.spec.ts | 38 ++++++++++++++++++++- packages/search/lib/commands/index.ts | 24 +++++++++++-- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 1a0a4f244bd..31eaf02dbba 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -1,7 +1,7 @@ import { strict as assert } from 'assert'; import testUtils, { GLOBAL } from '../test-utils'; import { transformArguments } from './CREATE'; -import { SchemaFieldTypes, SchemaTextFieldPhonetics, RedisSearchLanguages, VectorAlgorithms } from '.'; +import { SchemaFieldTypes, SchemaTextFieldPhonetics, RedisSearchLanguages, VectorAlgorithms, SCHEMA_GEO_SHAPE_COORD_SYSTEM } from '.'; describe('CREATE', () => { describe('transformArguments', () => { @@ -196,6 +196,42 @@ describe('CREATE', () => { }); }); + describe('GEOSHAPE', () => { + describe('without options', () => { + it('SCHEMA_FIELD_TYPE.GEOSHAPE', () => { + assert.deepEqual( + transformArguments('index', { + field: SchemaFieldTypes.GEOSHAPE + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE'] + ); + }); + + it('{ type: SCHEMA_FIELD_TYPE.GEOSHAPE }', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.GEOSHAPE + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE'] + ); + }); + }); + + it('with COORD_SYSTEM', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.GEOSHAPE, + COORD_SYSTEM: SCHEMA_GEO_SHAPE_COORD_SYSTEM.SPHERICAL + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'GEOSHAPE', 'COORD_SYSTEM', 'SPHERICAL'] + ); + }); + }); + describe('with generic options', () => { it('with AS', () => { assert.deepEqual( diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 75a2b4e380a..053e2fab38f 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -185,7 +185,8 @@ export enum SchemaFieldTypes { NUMERIC = 'NUMERIC', GEO = 'GEO', TAG = 'TAG', - VECTOR = 'VECTOR' + VECTOR = 'VECTOR', + GEOSHAPE = 'GEOSHAPE' } type CreateSchemaField< @@ -257,6 +258,17 @@ type CreateSchemaHNSWVectorField = CreateSchemaVectorField; +export const SCHEMA_GEO_SHAPE_COORD_SYSTEM = { + SPHERICAL: 'SPHERICAL', + FLAT: 'FLAT' +} as const; + +export type SchemaGeoShapeFieldCoordSystem = typeof SCHEMA_GEO_SHAPE_COORD_SYSTEM[keyof typeof SCHEMA_GEO_SHAPE_COORD_SYSTEM]; + +type CreateSchemaGeoShapeField = CreateSchemaCommonField; + export interface RediSearchSchema { [field: string]: CreateSchemaTextField | @@ -264,7 +276,8 @@ export interface RediSearchSchema { CreateSchemaGeoField | CreateSchemaTagField | CreateSchemaFlatVectorField | - CreateSchemaHNSWVectorField; + CreateSchemaHNSWVectorField | + CreateSchemaGeoShapeField } export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { @@ -361,6 +374,13 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema }); continue; // vector fields do not contain SORTABLE and NOINDEX options + + case SchemaFieldTypes.GEOSHAPE: + if (fieldOptions.COORD_SYSTEM !== undefined) { + args.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM); + } + + continue; // geo shape fields do not contain SORTABLE and NOINDEX options } if (fieldOptions.SORTABLE) { From 5576a0db492cda2cd88e09881bc330aa956dd0f5 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 10 Jul 2024 19:45:33 +0300 Subject: [PATCH 14/31] CAE-193: add "IGNORE" options to time series commands (for v4 branch) (#2752) --- packages/time-series/lib/commands/ADD.spec.ts | 16 +++++++++++++--- packages/time-series/lib/commands/ADD.ts | 9 +++++++++ packages/time-series/lib/commands/ALTER.spec.ts | 16 +++++++++++++--- packages/time-series/lib/commands/ALTER.ts | 6 +++++- packages/time-series/lib/commands/CREATE.spec.ts | 16 +++++++++++++--- packages/time-series/lib/commands/CREATE.ts | 7 ++++++- packages/time-series/lib/commands/index.ts | 6 ++++++ 7 files changed, 65 insertions(+), 11 deletions(-) diff --git a/packages/time-series/lib/commands/ADD.spec.ts b/packages/time-series/lib/commands/ADD.spec.ts index 94ad30627f8..07e67c1adec 100644 --- a/packages/time-series/lib/commands/ADD.spec.ts +++ b/packages/time-series/lib/commands/ADD.spec.ts @@ -57,16 +57,26 @@ describe('ADD', () => { ); }); - it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS', () => { + it('with IGNORE', () => { + assert.deepEqual( + transformArguments('key', '*', 1, { + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} + }), + ['TS.ADD', 'key', '*', '1', 'IGNORE', '1', '1'] + ) + }); + + it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS, IGNORE', () => { assert.deepEqual( transformArguments('key', '*', 1, { RETENTION: 1, ENCODING: TimeSeriesEncoding.UNCOMPRESSED, CHUNK_SIZE: 1, ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} }), - ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/ADD.ts b/packages/time-series/lib/commands/ADD.ts index 1988a964513..3ed185b9b75 100644 --- a/packages/time-series/lib/commands/ADD.ts +++ b/packages/time-series/lib/commands/ADD.ts @@ -8,14 +8,21 @@ import { Labels, pushLabelsArgument, Timestamp, + pushIgnoreArgument, } from '.'; +export interface TsIgnoreOptions { + MAX_TIME_DIFF: number; + MAX_VAL_DIFF: number; +} + interface AddOptions { RETENTION?: number; ENCODING?: TimeSeriesEncoding; CHUNK_SIZE?: number; ON_DUPLICATE?: TimeSeriesDuplicatePolicies; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export const FIRST_KEY_INDEX = 1; @@ -40,6 +47,8 @@ export function transformArguments(key: string, timestamp: Timestamp, value: num pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; } diff --git a/packages/time-series/lib/commands/ALTER.spec.ts b/packages/time-series/lib/commands/ALTER.spec.ts index cd066533aa4..7add3eeec3a 100644 --- a/packages/time-series/lib/commands/ALTER.spec.ts +++ b/packages/time-series/lib/commands/ALTER.spec.ts @@ -48,15 +48,25 @@ describe('ALTER', () => { ); }); - it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + it('with IGNORE with MAX_TIME_DIFF', () => { + assert.deepEqual( + transformArguments('key', { + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} + }), + ['TS.ALTER', 'key', 'IGNORE', '1', '1'] + ) + }); + + it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => { assert.deepEqual( transformArguments('key', { RETENTION: 1, CHUNK_SIZE: 1, DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} }), - ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/ALTER.ts b/packages/time-series/lib/commands/ALTER.ts index 7b9e1e774c6..576153a0cca 100644 --- a/packages/time-series/lib/commands/ALTER.ts +++ b/packages/time-series/lib/commands/ALTER.ts @@ -1,4 +1,5 @@ -import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy } from '.'; +import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy, pushIgnoreArgument } from '.'; +import { TsIgnoreOptions } from './ADD'; export const FIRST_KEY_INDEX = 1; @@ -7,6 +8,7 @@ interface AlterOptions { CHUNK_SIZE?: number; DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export function transformArguments(key: string, options?: AlterOptions): Array { @@ -20,6 +22,8 @@ export function transformArguments(key: string, options?: AlterOptions): Array { ['TS.CREATE', 'key', 'LABELS', 'label', 'value'] ); }); + + it('with IGNORE with MAX_TIME_DIFF', () => { + assert.deepEqual( + transformArguments('key', { + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} + }), + ['TS.CREATE', 'key', 'IGNORE', '1', '1'] + ) + }); - it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => { + it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => { assert.deepEqual( transformArguments('key', { RETENTION: 1, ENCODING: TimeSeriesEncoding.UNCOMPRESSED, CHUNK_SIZE: 1, DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, - LABELS: { label: 'value' } + LABELS: { label: 'value' }, + IGNORE: { MAX_TIME_DIFF: 1, MAX_VAL_DIFF: 1} }), - ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value'] + ['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1'] ); }); }); diff --git a/packages/time-series/lib/commands/CREATE.ts b/packages/time-series/lib/commands/CREATE.ts index a360950feff..a84d4b5f9fb 100644 --- a/packages/time-series/lib/commands/CREATE.ts +++ b/packages/time-series/lib/commands/CREATE.ts @@ -6,8 +6,10 @@ import { TimeSeriesDuplicatePolicies, Labels, pushLabelsArgument, - pushDuplicatePolicy + pushDuplicatePolicy, + pushIgnoreArgument } from '.'; +import { TsIgnoreOptions } from './ADD'; export const FIRST_KEY_INDEX = 1; @@ -17,6 +19,7 @@ interface CreateOptions { CHUNK_SIZE?: number; DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies; LABELS?: Labels; + IGNORE?: TsIgnoreOptions; } export function transformArguments(key: string, options?: CreateOptions): Array { @@ -32,6 +35,8 @@ export function transformArguments(key: string, options?: CreateOptions): Array< pushLabelsArgument(args, options?.LABELS); + pushIgnoreArgument(args, options?.IGNORE); + return args; } diff --git a/packages/time-series/lib/commands/index.ts b/packages/time-series/lib/commands/index.ts index 356b0416648..ca382498060 100644 --- a/packages/time-series/lib/commands/index.ts +++ b/packages/time-series/lib/commands/index.ts @@ -127,6 +127,12 @@ export function transformTimestampArgument(timestamp: Timestamp): string { ).toString(); } +export function pushIgnoreArgument(args: RedisCommandArguments, ignore?: ADD.TsIgnoreOptions) { + if (ignore !== undefined) { + args.push('IGNORE', ignore.MAX_TIME_DIFF.toString(), ignore.MAX_VAL_DIFF.toString()); + } +} + export function pushRetentionArgument(args: RedisCommandArguments, retention?: number): RedisCommandArguments { if (retention !== undefined) { args.push( From 64fca37944a2415ae735e2e046e22967b2b6d125 Mon Sep 17 00:00:00 2001 From: Gabriel Erzse Date: Sun, 14 Jul 2024 14:20:30 +0300 Subject: [PATCH 15/31] Support the NOVALUES option of HSCAN (#2711) * Support the NOVALUES option of HSCAN Issue #2705 The NOVALUES option instructs HSCAN to only return keys, without their values. This is materialized as a new command, `hScanNoValues`, given that the return type is different from the usual return type of `hScan`. Also a new iterator is provided, `hScanNoValuesIterator`, for the same reason. * skip hscan novalues test if redis < 7.4 * Also don't test hscan no values iterator < 7.4 --------- Co-authored-by: Shaya Potter --- packages/client/lib/client/index.spec.ts | 25 ++++++ packages/client/lib/client/index.ts | 13 ++- packages/client/lib/cluster/commands.ts | 3 + packages/client/lib/commands/HSCAN.spec.ts | 13 +++ packages/client/lib/commands/HSCAN.ts | 2 +- .../lib/commands/HSCAN_NOVALUES.spec.ts | 79 +++++++++++++++++++ .../client/lib/commands/HSCAN_NOVALUES.ts | 27 +++++++ 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 packages/client/lib/commands/HSCAN_NOVALUES.spec.ts create mode 100644 packages/client/lib/commands/HSCAN_NOVALUES.ts diff --git a/packages/client/lib/client/index.spec.ts b/packages/client/lib/client/index.spec.ts index 4442d3adb83..7f93efaa1c3 100644 --- a/packages/client/lib/client/index.spec.ts +++ b/packages/client/lib/client/index.spec.ts @@ -788,6 +788,31 @@ describe('Client', () => { assert.deepEqual(hash, results); }, GLOBAL.SERVERS.OPEN); + testUtils.testWithClient('hScanNoValuesIterator', async client => { + const hash: Record = {}; + const expectedKeys: Array = []; + for (let i = 0; i < 100; i++) { + hash[i.toString()] = i.toString(); + expectedKeys.push(i.toString()); + } + + await client.hSet('key', hash); + + const keys: Array = []; + for await (const key of client.hScanNoValuesIterator('key')) { + keys.push(key); + } + + function sort(a: string, b: string) { + return Number(a) - Number(b); + } + + assert.deepEqual(keys.sort(sort), expectedKeys); + }, { + ...GLOBAL.SERVERS.OPEN, + minimumDockerVersion: [7, 4] + }); + testUtils.testWithClient('sScanIterator', async client => { const members = new Set(); for (let i = 0; i < 100; i++) { diff --git a/packages/client/lib/client/index.ts b/packages/client/lib/client/index.ts index 4c3964c7aa0..d7f33e97b16 100644 --- a/packages/client/lib/client/index.ts +++ b/packages/client/lib/client/index.ts @@ -1,5 +1,5 @@ import COMMANDS from './commands'; -import { RedisCommand, RedisCommandArguments, RedisCommandRawReply, RedisCommandReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, RedisCommandSignature, ConvertArgumentType, RedisFunction, ExcludeMappedString, RedisCommands } from '../commands'; +import { RedisCommand, RedisCommandArgument, RedisCommandArguments, RedisCommandRawReply, RedisCommandReply, RedisFunctions, RedisModules, RedisExtensions, RedisScript, RedisScripts, RedisCommandSignature, ConvertArgumentType, RedisFunction, ExcludeMappedString, RedisCommands } from '../commands'; import RedisSocket, { RedisSocketOptions, RedisTlsSocketOptions } from './socket'; import RedisCommandsQueue, { QueueCommandOptions } from './commands-queue'; import RedisClientMultiCommand, { RedisClientMultiCommandType } from './multi-command'; @@ -820,6 +820,17 @@ export default class RedisClient< } while (cursor !== 0); } + async* hScanNoValuesIterator(key: string, options?: ScanOptions): AsyncIterable> { + let cursor = 0; + do { + const reply = await (this as any).hScanNoValues(key, cursor, options); + cursor = reply.cursor; + for (const k of reply.keys) { + yield k; + } + } while (cursor !== 0); + } + async* sScanIterator(key: string, options?: ScanOptions): AsyncIterable { let cursor = 0; do { diff --git a/packages/client/lib/cluster/commands.ts b/packages/client/lib/cluster/commands.ts index b6913b40686..9027c5c0b5e 100644 --- a/packages/client/lib/cluster/commands.ts +++ b/packages/client/lib/cluster/commands.ts @@ -72,6 +72,7 @@ import * as HRANDFIELD_COUNT_WITHVALUES from '../commands/HRANDFIELD_COUNT_WITHV import * as HRANDFIELD_COUNT from '../commands/HRANDFIELD_COUNT'; import * as HRANDFIELD from '../commands/HRANDFIELD'; import * as HSCAN from '../commands/HSCAN'; +import * as HSCAN_NOVALUES from '../commands/HSCAN_NOVALUES'; import * as HSET from '../commands/HSET'; import * as HSETNX from '../commands/HSETNX'; import * as HSTRLEN from '../commands/HSTRLEN'; @@ -368,6 +369,8 @@ export default { hRandField: HRANDFIELD, HSCAN, hScan: HSCAN, + HSCAN_NOVALUES, + hScanNoValues: HSCAN_NOVALUES, HSET, hSet: HSET, HSETNX, diff --git a/packages/client/lib/commands/HSCAN.spec.ts b/packages/client/lib/commands/HSCAN.spec.ts index b426763b99b..6757888a875 100644 --- a/packages/client/lib/commands/HSCAN.spec.ts +++ b/packages/client/lib/commands/HSCAN.spec.ts @@ -73,5 +73,18 @@ describe('HSCAN', () => { tuples: [] } ); + + await Promise.all([ + client.hSet('key', 'a', '1'), + client.hSet('key', 'b', '2') + ]); + + assert.deepEqual( + await client.hScan('key', 0), + { + cursor: 0, + tuples: [{field: 'a', value: '1'}, {field: 'b', value: '2'}] + } + ); }, GLOBAL.SERVERS.OPEN); }); diff --git a/packages/client/lib/commands/HSCAN.ts b/packages/client/lib/commands/HSCAN.ts index ba18fb986bc..5167693b604 100644 --- a/packages/client/lib/commands/HSCAN.ts +++ b/packages/client/lib/commands/HSCAN.ts @@ -16,7 +16,7 @@ export function transformArguments( ], cursor, options); } -type HScanRawReply = [RedisCommandArgument, Array]; +export type HScanRawReply = [RedisCommandArgument, Array]; export interface HScanTuple { field: RedisCommandArgument; diff --git a/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts b/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts new file mode 100644 index 00000000000..7e05b841e43 --- /dev/null +++ b/packages/client/lib/commands/HSCAN_NOVALUES.spec.ts @@ -0,0 +1,79 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../test-utils'; +import { transformArguments, transformReply } from './HSCAN_NOVALUES'; + +describe('HSCAN_NOVALUES', () => { + testUtils.isVersionGreaterThanHook([7, 4]); + + describe('transformArguments', () => { + it('cusror only', () => { + assert.deepEqual( + transformArguments('key', 0), + ['HSCAN', 'key', '0', 'NOVALUES'] + ); + }); + + it('with MATCH', () => { + assert.deepEqual( + transformArguments('key', 0, { + MATCH: 'pattern' + }), + ['HSCAN', 'key', '0', 'MATCH', 'pattern', 'NOVALUES'] + ); + }); + + it('with COUNT', () => { + assert.deepEqual( + transformArguments('key', 0, { + COUNT: 1 + }), + ['HSCAN', 'key', '0', 'COUNT', '1', 'NOVALUES'] + ); + }); + }); + + describe('transformReply', () => { + it('without keys', () => { + assert.deepEqual( + transformReply(['0', []]), + { + cursor: 0, + keys: [] + } + ); + }); + + it('with keys', () => { + assert.deepEqual( + transformReply(['0', ['key1', 'key2']]), + { + cursor: 0, + keys: ['key1', 'key2'] + } + ); + }); + }); + + testUtils.testWithClient('client.hScanNoValues', async client => { + assert.deepEqual( + await client.hScanNoValues('key', 0), + { + cursor: 0, + keys: [] + } + ); + + await Promise.all([ + client.hSet('key', 'a', '1'), + client.hSet('key', 'b', '2') + ]); + + assert.deepEqual( + await client.hScanNoValues('key', 0), + { + cursor: 0, + keys: ['a', 'b'] + } + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/client/lib/commands/HSCAN_NOVALUES.ts b/packages/client/lib/commands/HSCAN_NOVALUES.ts new file mode 100644 index 00000000000..bde5d846430 --- /dev/null +++ b/packages/client/lib/commands/HSCAN_NOVALUES.ts @@ -0,0 +1,27 @@ +import { RedisCommandArgument, RedisCommandArguments } from '.'; +import { ScanOptions } from './generic-transformers'; +import { HScanRawReply, transformArguments as transformHScanArguments } from './HSCAN'; + +export { FIRST_KEY_INDEX, IS_READ_ONLY } from './HSCAN'; + +export function transformArguments( + key: RedisCommandArgument, + cursor: number, + options?: ScanOptions +): RedisCommandArguments { + const args = transformHScanArguments(key, cursor, options); + args.push('NOVALUES'); + return args; +} + +interface HScanNoValuesReply { + cursor: number; + keys: Array; +} + +export function transformReply([cursor, rawData]: HScanRawReply): HScanNoValuesReply { + return { + cursor: Number(cursor), + keys: [...rawData] + }; +} From 0e7e2e6e2964ab7b0d0455b23b9b6adc489e5e53 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 17 Jul 2024 11:36:45 +0300 Subject: [PATCH 16/31] add missing fields support to schema (v4) (#2789) --- packages/search/lib/commands/CREATE.spec.ts | 30 ++++++++++++++++++ packages/search/lib/commands/index.ts | 35 +++++++++++++++++++-- 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 31eaf02dbba..094ba4529f0 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -441,6 +441,36 @@ describe('CREATE', () => { ); }); }); + + describe('Missing Values', () => { + it('with INDEXEMPTY', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + MISSING_VALUES: { + INDEXEMPTY: true + } + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXEMPTY'] + ); + }); + + it('with INDEXMISSING', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + MISSING_VALUES: { + INDEXMISSING: true + } + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXMISSING'] + ); + }); + }); }); testUtils.testWithClient('client.ft.create', async client => { diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 053e2fab38f..29dbd2480ce 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -189,12 +189,32 @@ export enum SchemaFieldTypes { GEOSHAPE = 'GEOSHAPE' } +export interface MissingValues { + INDEXEMPTY?: boolean; + INDEXMISSING?: boolean; +} + +function pushMissingValues(args: RedisCommandArguments, missingValues?: MissingValues) { + if (!missingValues) { + return; + } + + if (missingValues.INDEXEMPTY) { + args.push("INDEXEMPTY"); + } + + if (missingValues.INDEXMISSING) { + args.push("INDEXMISSING"); + } +} + type CreateSchemaField< T extends SchemaFieldTypes, E = Record > = T | ({ type: T; AS?: string; + MISSING_VALUES?: MissingValues; } & E); type CreateSchemaCommonField< @@ -313,11 +333,14 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema args.push('WITHSUFFIXTRIE'); } + pushMissingValues(args, fieldOptions.MISSING_VALUES); + break; - // case SchemaFieldTypes.NUMERIC: - // case SchemaFieldTypes.GEO: - // break; + case SchemaFieldTypes.NUMERIC: + case SchemaFieldTypes.GEO: + pushMissingValues(args, fieldOptions.MISSING_VALUES); + break; case SchemaFieldTypes.TAG: if (fieldOptions.SEPARATOR) { @@ -332,6 +355,8 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema args.push('WITHSUFFIXTRIE'); } + pushMissingValues(args, fieldOptions.MISSING_VALUES); + break; case SchemaFieldTypes.VECTOR: @@ -373,6 +398,8 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema } }); + pushMissingValues(args, fieldOptions.MISSING_VALUES); + continue; // vector fields do not contain SORTABLE and NOINDEX options case SchemaFieldTypes.GEOSHAPE: @@ -380,6 +407,8 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema args.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM); } + pushMissingValues(args, fieldOptions.MISSING_VALUES); + continue; // geo shape fields do not contain SORTABLE and NOINDEX options } From d09aaa311d45978ae0b97e4c189bc180ed85c9b0 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Tue, 23 Jul 2024 19:59:27 +0300 Subject: [PATCH 17/31] small internal tweak for maxage per discussion w/ leibele (#2803) --- packages/client/lib/commands/CLIENT_KILL.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/client/lib/commands/CLIENT_KILL.ts b/packages/client/lib/commands/CLIENT_KILL.ts index f0b31e5cac0..b1a53df64d8 100644 --- a/packages/client/lib/commands/CLIENT_KILL.ts +++ b/packages/client/lib/commands/CLIENT_KILL.ts @@ -38,11 +38,11 @@ type KillSkipMe = ClientKillFilters.SKIP_ME | (KillFilter { +interface KillMaxAge extends KillFilter { maxAge: number; } -type KillFilters = KillAddress | KillLocalAddress | KillId | KillType | KillUser | KillSkipMe | KillMaxage; +type KillFilters = KillAddress | KillLocalAddress | KillId | KillType | KillUser | KillSkipMe | KillMaxAge; export function transformArguments(filters: KillFilters | Array): RedisCommandArguments { const args = ['CLIENT', 'KILL']; From b884e132fa54908b022f565263d1402b43cec83a Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Tue, 23 Jul 2024 21:07:32 +0300 Subject: [PATCH 18/31] don't expand/copy rawValues, return it directly. (#2800) --- packages/client/lib/commands/HSCAN_NOVALUES.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/lib/commands/HSCAN_NOVALUES.ts b/packages/client/lib/commands/HSCAN_NOVALUES.ts index bde5d846430..37a929754c6 100644 --- a/packages/client/lib/commands/HSCAN_NOVALUES.ts +++ b/packages/client/lib/commands/HSCAN_NOVALUES.ts @@ -22,6 +22,6 @@ interface HScanNoValuesReply { export function transformReply([cursor, rawData]: HScanRawReply): HScanNoValuesReply { return { cursor: Number(cursor), - keys: [...rawData] + keys: rawData }; } From 6f79b49f731a1aaf57f42e16ea72774f062e57a1 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Wed, 24 Jul 2024 20:15:01 +0300 Subject: [PATCH 19/31] updated per discussion w/ leibele (#2804) --- packages/client/lib/commands/HEXPIRE.ts | 8 ++++---- packages/client/lib/commands/HEXPIRETIME.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/client/lib/commands/HEXPIRE.ts b/packages/client/lib/commands/HEXPIRE.ts index 032790c40bb..938f9039939 100644 --- a/packages/client/lib/commands/HEXPIRE.ts +++ b/packages/client/lib/commands/HEXPIRE.ts @@ -8,16 +8,16 @@ import { pushVerdictArgument } from './generic-transformers'; export const HASH_EXPIRATION = { /** @property {number} */ /** The field does not exist */ - FieldNotExists: -2, + FIELD_NOT_EXISTS: -2, /** @property {number} */ /** Specified NX | XX | GT | LT condition not met */ - ConditionNotMet: 0, + CONDITION_NOT_MET: 0, /** @property {number} */ /** Expiration time was set or updated */ - Updated: 1, + UPDATED: 1, /** @property {number} */ /** Field deleted because the specified expiration time is in the past */ - Deleted: 2 + DELETED: 2 } as const; export type HashExpiration = typeof HASH_EXPIRATION[keyof typeof HASH_EXPIRATION]; diff --git a/packages/client/lib/commands/HEXPIRETIME.ts b/packages/client/lib/commands/HEXPIRETIME.ts index 55ae577f9d0..01764b1032d 100644 --- a/packages/client/lib/commands/HEXPIRETIME.ts +++ b/packages/client/lib/commands/HEXPIRETIME.ts @@ -4,10 +4,10 @@ import { pushVerdictArgument } from './generic-transformers'; export const HASH_EXPIRATION_TIME = { /** @property {number} */ /** The field does not exist */ - FieldNotExists: -2, + FIELD_NOT_EXISTS: -2, /** @property {number} */ /** The field exists but has no associated expire */ - NoExpiration: -1, + NO_EXPIRATION: -1, } as const; export const FIRST_KEY_INDEX = 1 From 54b3e178f9943ae24362cb99c8d91ac865cae8b4 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Mon, 29 Jul 2024 16:22:38 +0300 Subject: [PATCH 20/31] add addscores to aggregate search command (#2799) * add addscores to aggregate search command * change `true` to `boolean` --------- Co-authored-by: Leibale Eidelman --- packages/search/lib/commands/AGGREGATE.spec.ts | 7 +++++++ packages/search/lib/commands/AGGREGATE.ts | 9 +++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/search/lib/commands/AGGREGATE.spec.ts b/packages/search/lib/commands/AGGREGATE.spec.ts index d1e4565339a..5b34d7dc16f 100644 --- a/packages/search/lib/commands/AGGREGATE.spec.ts +++ b/packages/search/lib/commands/AGGREGATE.spec.ts @@ -19,6 +19,13 @@ describe('AGGREGATE', () => { ); }); + it('with ADDSCORES', () => { + assert.deepEqual( + transformArguments('index', '*', { ADDSCORES: true }), + ['FT.AGGREGATE', 'index', '*', 'ADDSCORES'] + ); + }); + describe('with LOAD', () => { describe('single', () => { describe('without alias', () => { diff --git a/packages/search/lib/commands/AGGREGATE.ts b/packages/search/lib/commands/AGGREGATE.ts index 950d959243a..0cab9b25d48 100644 --- a/packages/search/lib/commands/AGGREGATE.ts +++ b/packages/search/lib/commands/AGGREGATE.ts @@ -119,7 +119,8 @@ type LoadField = PropertyName | { } export interface AggregateOptions { - VERBATIM?: true; + VERBATIM?: boolean; + ADDSCORES?: boolean; LOAD?: LoadField | Array; STEPS?: Array; PARAMS?: Params; @@ -150,6 +151,10 @@ export function pushAggregatehOptions( args.push('VERBATIM'); } + if (options?.ADDSCORES) { + args.push('ADDSCORES'); + } + if (options?.LOAD) { args.push('LOAD'); pushArgumentsWithLength(args, () => { @@ -308,4 +313,4 @@ export function transformReply(rawReply: AggregateRawReply): AggregateReply { total: rawReply[0], results }; -} \ No newline at end of file +} From dc3be85db7a4d64f8d15b80ccb72e6c1282e71c2 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Mon, 29 Jul 2024 16:24:02 +0300 Subject: [PATCH 21/31] add 7.4-rc2 to github action test suite (#2793) * add 7.4-rc2 to github action test suite * Update tests.yml --------- Co-authored-by: Leibale Eidelman --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 99181e08e5e..852691b3c82 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: node-version: ['18', '20'] - redis-version: ['5', '6.0', '6.2', '7.0', '7.2'] + redis-version: ['5', '6.0', '6.2', '7.0', '7.2', '7.4'] steps: - uses: actions/checkout@v4 with: From 179b9e009422235982a1e706c8ac79fd9e3496c0 Mon Sep 17 00:00:00 2001 From: Marco Reni Date: Mon, 29 Jul 2024 15:25:03 +0200 Subject: [PATCH 22/31] fix: json.mget should be readonly (#2807) (#2808) * fix: json.mget should be readonly (#2807) * lint --- packages/json/lib/commands/MGET.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/json/lib/commands/MGET.ts b/packages/json/lib/commands/MGET.ts index 582b73bf85a..34ca8da289f 100644 --- a/packages/json/lib/commands/MGET.ts +++ b/packages/json/lib/commands/MGET.ts @@ -2,6 +2,8 @@ import { RedisJSON, transformRedisJsonNullReply } from '.'; export const FIRST_KEY_INDEX = 1; +export const IS_READ_ONLY = true; + export function transformArguments(keys: Array, path: string): Array { return [ 'JSON.MGET', From 840ec57fb965ad66113608cd8e80154a4db3b2e6 Mon Sep 17 00:00:00 2001 From: Shaya Potter Date: Mon, 29 Jul 2024 16:27:53 +0300 Subject: [PATCH 23/31] small refactor per discussion with leibele (#2801) * small refactor per discussion with leibele * move true type to boolean type * fix geoshape to support NOINDEX & SORTABLE, clean code * fix for last commit --------- Co-authored-by: Leibale Eidelman --- packages/search/lib/commands/CREATE.spec.ts | 66 ++++++++-------- packages/search/lib/commands/index.ts | 83 ++++++++++----------- 2 files changed, 76 insertions(+), 73 deletions(-) diff --git a/packages/search/lib/commands/CREATE.spec.ts b/packages/search/lib/commands/CREATE.spec.ts index 094ba4529f0..50c5c011c89 100644 --- a/packages/search/lib/commands/CREATE.spec.ts +++ b/packages/search/lib/commands/CREATE.spec.ts @@ -70,6 +70,18 @@ describe('CREATE', () => { ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'WITHSUFFIXTRIE'] ); }); + + it('with INDEXEMPTY', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + INDEXEMPTY: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXEMPTY'] + ); + }); }); it('NUMERIC', () => { @@ -148,6 +160,18 @@ describe('CREATE', () => { ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'WITHSUFFIXTRIE'] ); }); + + it('with INDEXEMPTY', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TAG, + INDEXEMPTY: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TAG', 'INDEXEMPTY'] + ); + }); }); describe('VECTOR', () => { @@ -282,6 +306,18 @@ describe('CREATE', () => { ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'NOINDEX'] ); }); + + it('with INDEXMISSING', () => { + assert.deepEqual( + transformArguments('index', { + field: { + type: SchemaFieldTypes.TEXT, + INDEXMISSING: true + } + }), + ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXMISSING'] + ); + }); }); }); @@ -441,36 +477,6 @@ describe('CREATE', () => { ); }); }); - - describe('Missing Values', () => { - it('with INDEXEMPTY', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - MISSING_VALUES: { - INDEXEMPTY: true - } - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXEMPTY'] - ); - }); - - it('with INDEXMISSING', () => { - assert.deepEqual( - transformArguments('index', { - field: { - type: SchemaFieldTypes.TEXT, - MISSING_VALUES: { - INDEXMISSING: true - } - } - }), - ['FT.CREATE', 'index', 'SCHEMA', 'field', 'TEXT', 'INDEXMISSING'] - ); - }); - }); }); testUtils.testWithClient('client.ft.create', async client => { diff --git a/packages/search/lib/commands/index.ts b/packages/search/lib/commands/index.ts index 29dbd2480ce..f907e1999e6 100644 --- a/packages/search/lib/commands/index.ts +++ b/packages/search/lib/commands/index.ts @@ -188,25 +188,6 @@ export enum SchemaFieldTypes { VECTOR = 'VECTOR', GEOSHAPE = 'GEOSHAPE' } - -export interface MissingValues { - INDEXEMPTY?: boolean; - INDEXMISSING?: boolean; -} - -function pushMissingValues(args: RedisCommandArguments, missingValues?: MissingValues) { - if (!missingValues) { - return; - } - - if (missingValues.INDEXEMPTY) { - args.push("INDEXEMPTY"); - } - - if (missingValues.INDEXMISSING) { - args.push("INDEXMISSING"); - } -} type CreateSchemaField< T extends SchemaFieldTypes, @@ -214,20 +195,36 @@ type CreateSchemaField< > = T | ({ type: T; AS?: string; - MISSING_VALUES?: MissingValues; + INDEXMISSING?: boolean; } & E); +type CommonFieldArguments = { + SORTABLE?: boolean | 'UNF'; + NOINDEX?: boolean; +}; + type CreateSchemaCommonField< T extends SchemaFieldTypes, E = Record > = CreateSchemaField< T, - ({ - SORTABLE?: true | 'UNF'; - NOINDEX?: true; - } & E) + (CommonFieldArguments & E) >; +function pushCommonFieldArguments(args: RedisCommandArguments, fieldOptions: CommonFieldArguments) { + if (fieldOptions.SORTABLE) { + args.push('SORTABLE'); + + if (fieldOptions.SORTABLE === 'UNF') { + args.push('UNF'); + } + } + + if (fieldOptions.NOINDEX) { + args.push('NOINDEX'); + } +} + export enum SchemaTextFieldPhonetics { DM_EN = 'dm:en', DM_FR = 'dm:fr', @@ -240,6 +237,7 @@ type CreateSchemaTextField = CreateSchemaCommonField; type CreateSchemaNumericField = CreateSchemaCommonField; @@ -250,6 +248,7 @@ type CreateSchemaTagField = CreateSchemaCommonField; export enum VectorAlgorithms { @@ -297,7 +296,7 @@ export interface RediSearchSchema { CreateSchemaTagField | CreateSchemaFlatVectorField | CreateSchemaHNSWVectorField | - CreateSchemaGeoShapeField + CreateSchemaGeoShapeField; } export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema) { @@ -333,13 +332,17 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema args.push('WITHSUFFIXTRIE'); } - pushMissingValues(args, fieldOptions.MISSING_VALUES); + pushCommonFieldArguments(args, fieldOptions); + + if (fieldOptions.INDEXEMPTY) { + args.push('INDEXEMPTY'); + } break; case SchemaFieldTypes.NUMERIC: case SchemaFieldTypes.GEO: - pushMissingValues(args, fieldOptions.MISSING_VALUES); + pushCommonFieldArguments(args, fieldOptions); break; case SchemaFieldTypes.TAG: @@ -355,7 +358,11 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema args.push('WITHSUFFIXTRIE'); } - pushMissingValues(args, fieldOptions.MISSING_VALUES); + pushCommonFieldArguments(args, fieldOptions); + + if (fieldOptions.INDEXEMPTY) { + args.push('INDEXEMPTY'); + } break; @@ -398,30 +405,20 @@ export function pushSchema(args: RedisCommandArguments, schema: RediSearchSchema } }); - pushMissingValues(args, fieldOptions.MISSING_VALUES); - - continue; // vector fields do not contain SORTABLE and NOINDEX options + break; case SchemaFieldTypes.GEOSHAPE: if (fieldOptions.COORD_SYSTEM !== undefined) { args.push('COORD_SYSTEM', fieldOptions.COORD_SYSTEM); } - pushMissingValues(args, fieldOptions.MISSING_VALUES); - - continue; // geo shape fields do not contain SORTABLE and NOINDEX options - } - - if (fieldOptions.SORTABLE) { - args.push('SORTABLE'); + pushCommonFieldArguments(args, fieldOptions); - if (fieldOptions.SORTABLE === 'UNF') { - args.push('UNF'); - } + break; } - if (fieldOptions.NOINDEX) { - args.push('NOINDEX'); + if (fieldOptions.INDEXMISSING) { + args.push('INDEXMISSING'); } } } From 3973fa24e1c658b3c5395cf439b02d215b979719 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 09:39:21 -0400 Subject: [PATCH 24/31] Release json@1.0.7 --- packages/json/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/json/package.json b/packages/json/package.json index 3a168b7d4b5..ad60cc13c26 100644 --- a/packages/json/package.json +++ b/packages/json/package.json @@ -1,6 +1,6 @@ { "name": "@redis/json", - "version": "1.0.6", + "version": "1.0.7", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 49ef273df2727fa3007a460d828958276f408d52 Mon Sep 17 00:00:00 2001 From: Leibale Eidelman Date: Mon, 29 Jul 2024 09:56:39 -0400 Subject: [PATCH 25/31] Update tests.yml --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 852691b3c82..84d70d6b4c0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: fail-fast: false matrix: node-version: ['18', '20'] - redis-version: ['5', '6.0', '6.2', '7.0', '7.2', '7.4'] + redis-version: ['5', '6.0', '6.2', '7.0', '7.2', '7.4-rc2'] steps: - uses: actions/checkout@v4 with: From 18ccc28c2fb5629fc47aa6450f1efa964e363ddd Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:11:04 -0400 Subject: [PATCH 26/31] fix hash expiration tests --- packages/client/lib/commands/HEXPIRE.spec.ts | 2 +- packages/client/lib/commands/HEXPIREAT.spec.ts | 2 +- packages/client/lib/commands/HEXPIRETIME.spec.ts | 2 +- packages/client/lib/commands/HPERSIST.spec.ts | 2 +- packages/client/lib/commands/HPEXPIRE.spec.ts | 2 +- packages/client/lib/commands/HPEXPIREAT.spec.ts | 2 +- packages/client/lib/commands/HPEXPIRETIME.spec.ts | 2 +- packages/client/lib/commands/HPTTL.spec.ts | 2 +- packages/client/lib/commands/HTTL.spec.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/client/lib/commands/HEXPIRE.spec.ts b/packages/client/lib/commands/HEXPIRE.spec.ts index 40f841b3af8..3714f617f58 100644 --- a/packages/client/lib/commands/HEXPIRE.spec.ts +++ b/packages/client/lib/commands/HEXPIRE.spec.ts @@ -32,7 +32,7 @@ describe('HEXPIRE', () => { testUtils.testWithClient('hexpire', async client => { assert.deepEqual( await client.hExpire('key', ['field1'], 0), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN diff --git a/packages/client/lib/commands/HEXPIREAT.spec.ts b/packages/client/lib/commands/HEXPIREAT.spec.ts index 2ab969eb02e..1c65fb61773 100644 --- a/packages/client/lib/commands/HEXPIREAT.spec.ts +++ b/packages/client/lib/commands/HEXPIREAT.spec.ts @@ -41,7 +41,7 @@ describe('HEXPIREAT', () => { testUtils.testWithClient('expireAt', async client => { assert.deepEqual( await client.hExpireAt('key', 'field1', 1), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/HEXPIRETIME.spec.ts b/packages/client/lib/commands/HEXPIRETIME.spec.ts index 4e5ab82a7e9..9c3eb024bed 100644 --- a/packages/client/lib/commands/HEXPIRETIME.spec.ts +++ b/packages/client/lib/commands/HEXPIRETIME.spec.ts @@ -24,7 +24,7 @@ describe('HEXPIRETIME', () => { testUtils.testWithClient('hExpireTime', async client => { assert.deepEqual( await client.hExpireTime('key', 'field1'), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/HPERSIST.spec.ts b/packages/client/lib/commands/HPERSIST.spec.ts index 594dc30cf74..8cf3f1fe221 100644 --- a/packages/client/lib/commands/HPERSIST.spec.ts +++ b/packages/client/lib/commands/HPERSIST.spec.ts @@ -25,7 +25,7 @@ describe('HPERSIST', () => { testUtils.testWithClient('hPersist', async client => { assert.deepEqual( await client.hPersist('key', 'field1'), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/HPEXPIRE.spec.ts b/packages/client/lib/commands/HPEXPIRE.spec.ts index fd11ea359cf..852d9f5bd21 100644 --- a/packages/client/lib/commands/HPEXPIRE.spec.ts +++ b/packages/client/lib/commands/HPEXPIRE.spec.ts @@ -32,7 +32,7 @@ describe('HEXPIRE', () => { testUtils.testWithClient('hexpire', async client => { assert.deepEqual( await client.hpExpire('key', ['field1'], 0), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN diff --git a/packages/client/lib/commands/HPEXPIREAT.spec.ts b/packages/client/lib/commands/HPEXPIREAT.spec.ts index abe49f1d8d7..9747cca1a2d 100644 --- a/packages/client/lib/commands/HPEXPIREAT.spec.ts +++ b/packages/client/lib/commands/HPEXPIREAT.spec.ts @@ -40,7 +40,7 @@ describe('HPEXPIREAT', () => { testUtils.testWithClient('hpExpireAt', async client => { assert.deepEqual( await client.hpExpireAt('key', ['field1'], 1), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN, diff --git a/packages/client/lib/commands/HPEXPIRETIME.spec.ts b/packages/client/lib/commands/HPEXPIRETIME.spec.ts index afaa46a7793..ff03b73c71d 100644 --- a/packages/client/lib/commands/HPEXPIRETIME.spec.ts +++ b/packages/client/lib/commands/HPEXPIRETIME.spec.ts @@ -25,7 +25,7 @@ describe('HPEXPIRETIME', () => { testUtils.testWithClient('hpExpireTime', async client => { assert.deepEqual( await client.hpExpireTime('key', 'field1'), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN diff --git a/packages/client/lib/commands/HPTTL.spec.ts b/packages/client/lib/commands/HPTTL.spec.ts index 0bf10c860e0..ddca26ea85b 100644 --- a/packages/client/lib/commands/HPTTL.spec.ts +++ b/packages/client/lib/commands/HPTTL.spec.ts @@ -25,7 +25,7 @@ describe('HPTTL', () => { testUtils.testWithClient('hpTTL', async client => { assert.deepEqual( await client.hpTTL('key', 'field1'), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN diff --git a/packages/client/lib/commands/HTTL.spec.ts b/packages/client/lib/commands/HTTL.spec.ts index a36c681299e..21b8b329a5d 100644 --- a/packages/client/lib/commands/HTTL.spec.ts +++ b/packages/client/lib/commands/HTTL.spec.ts @@ -26,7 +26,7 @@ describe('HTTL', () => { testUtils.testWithClient('hTTL', async client => { assert.deepEqual( await client.hTTL('key', 'field1'), - [ HASH_EXPIRATION_TIME.FieldNotExists ] + [HASH_EXPIRATION_TIME.FIELD_NOT_EXISTS] ); }, { ...GLOBAL.SERVERS.OPEN From fff7b006c393e2b4e78e4f953398dfd24ed78ee0 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:25:26 -0400 Subject: [PATCH 27/31] Release search@1.2.0 --- packages/search/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/search/package.json b/packages/search/package.json index 9fb1d0e002d..aaf9bc50f11 100644 --- a/packages/search/package.json +++ b/packages/search/package.json @@ -1,6 +1,6 @@ { "name": "@redis/search", - "version": "1.1.6", + "version": "1.2.0", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 268ceda6259f8fafe04f456311fa395df116b50d Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:27:51 -0400 Subject: [PATCH 28/31] Release time-series@1.1.0 --- packages/time-series/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/time-series/package.json b/packages/time-series/package.json index ee3c7526192..65ee1e99c23 100644 --- a/packages/time-series/package.json +++ b/packages/time-series/package.json @@ -1,6 +1,6 @@ { "name": "@redis/time-series", - "version": "1.0.5", + "version": "1.1.0", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From b493afac60b7294446aaf80853d17a0200d1ab5c Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:29:17 -0400 Subject: [PATCH 29/31] Release client@1.6.0 --- packages/client/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/package.json b/packages/client/package.json index 026e4261786..e344edd52c3 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@redis/client", - "version": "1.5.17", + "version": "1.6.0", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts", From 878fb69591fb1877823bec6876eb22025a3815b2 Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:32:42 -0400 Subject: [PATCH 30/31] upgrade deps --- package-lock.json | 16 ++++++++-------- package.json | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 11ae2a61088..9fc773717d7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,11 +13,11 @@ ], "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.17", + "@redis/client": "1.6.0", "@redis/graph": "1.1.1", - "@redis/json": "1.0.6", - "@redis/search": "1.1.6", - "@redis/time-series": "1.0.5" + "@redis/json": "1.0.7", + "@redis/search": "1.2.0", + "@redis/time-series": "1.1.0" }, "devDependencies": { "@tsconfig/node14": "^14.1.0", @@ -8838,7 +8838,7 @@ }, "packages/client": { "name": "@redis/client", - "version": "1.5.17", + "version": "1.6.0", "license": "MIT", "dependencies": { "cluster-key-slot": "1.1.2", @@ -8887,7 +8887,7 @@ }, "packages/json": { "name": "@redis/json", - "version": "1.0.6", + "version": "1.0.7", "license": "MIT", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", @@ -8906,7 +8906,7 @@ }, "packages/search": { "name": "@redis/search", - "version": "1.1.6", + "version": "1.2.0", "license": "MIT", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", @@ -8943,7 +8943,7 @@ }, "packages/time-series": { "name": "@redis/time-series", - "version": "1.0.5", + "version": "1.1.0", "license": "MIT", "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.2", diff --git a/package.json b/package.json index 586ef8b8dad..9aaec4d2ae9 100644 --- a/package.json +++ b/package.json @@ -24,11 +24,11 @@ }, "dependencies": { "@redis/bloom": "1.2.0", - "@redis/client": "1.5.17", + "@redis/client": "1.6.0", "@redis/graph": "1.1.1", - "@redis/json": "1.0.6", - "@redis/search": "1.1.6", - "@redis/time-series": "1.0.5" + "@redis/json": "1.0.7", + "@redis/search": "1.2.0", + "@redis/time-series": "1.1.0" }, "devDependencies": { "@tsconfig/node14": "^14.1.0", From 2fc79bdfb375602e2aaba15962f57c88d8afe46b Mon Sep 17 00:00:00 2001 From: Leibale Date: Mon, 29 Jul 2024 10:34:21 -0400 Subject: [PATCH 31/31] Release redis@4.7.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9fc773717d7..18a7003947e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "redis", - "version": "4.6.15", + "version": "4.7.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "redis", - "version": "4.6.15", + "version": "4.7.0", "license": "MIT", "workspaces": [ "./packages/*" diff --git a/package.json b/package.json index 9aaec4d2ae9..e8ceef7173d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "redis", "description": "A modern, high performance Redis client", - "version": "4.6.15", + "version": "4.7.0", "license": "MIT", "main": "./dist/index.js", "types": "./dist/index.d.ts",