diff --git a/packages/bloom/lib/commands/index.ts b/packages/bloom/lib/commands/index.ts index 665664a75b..cea55b2a7c 100644 --- a/packages/bloom/lib/commands/index.ts +++ b/packages/bloom/lib/commands/index.ts @@ -1,11 +1,13 @@ -import Bloom from './bloom'; -import CountMinSketch from './count-min-sketch'; -import Cuckoo from './cuckoo'; -import TopK from './top-k'; +import bf from './bloom'; +import cms from './count-min-sketch'; +import cf from './cuckoo'; +import tDigest from './t-digest'; +import topK from './top-k'; export default { - bf: Bloom, - cms: CountMinSketch, - cf: Cuckoo, - topK: TopK + bf, + cms, + cf, + tDigest, + topK }; diff --git a/packages/bloom/lib/commands/t-digest/ADD.spec.ts b/packages/bloom/lib/commands/t-digest/ADD.spec.ts new file mode 100644 index 0000000000..3e1dbff7f2 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/ADD.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './ADD'; + +describe('TDIGEST.ADD', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.ADD', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.add', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.add('key', [1]) + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/ADD.ts b/packages/bloom/lib/commands/t-digest/ADD.ts new file mode 100644 index 0000000000..941e853100 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/ADD.ts @@ -0,0 +1,17 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + key: RedisCommandArgument, + values: Array +): RedisCommandArguments { + const args = ['TDIGEST.ADD', key]; + for (const item of values) { + args.push(item.toString()); + } + + return args; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts new file mode 100644 index 0000000000..083f09d22a --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/BYRANK.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './BYRANK'; + +describe('TDIGEST.BYRANK', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.BYRANK', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.byRank', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.byRank('key', [1]) + ]); + + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/BYRANK.ts b/packages/bloom/lib/commands/t-digest/BYRANK.ts new file mode 100644 index 0000000000..5684385b4d --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/BYRANK.ts @@ -0,0 +1,19 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + ranks: Array +): RedisCommandArguments { + const args = ['TDIGEST.BYRANK', key]; + for (const rank of ranks) { + args.push(rank.toString()); + } + + return args; +} + +export { transformDoublesReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts new file mode 100644 index 0000000000..c094f36e71 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/BYREVRANK.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './BYREVRANK'; + +describe('TDIGEST.BYREVRANK', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.BYREVRANK', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.byRevRank', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.byRevRank('key', [1]) + ]); + + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/BYREVRANK.ts b/packages/bloom/lib/commands/t-digest/BYREVRANK.ts new file mode 100644 index 0000000000..3dcf3a973c --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/BYREVRANK.ts @@ -0,0 +1,19 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + ranks: Array +): RedisCommandArguments { + const args = ['TDIGEST.BYREVRANK', key]; + for (const rank of ranks) { + args.push(rank.toString()); + } + + return args; +} + +export { transformDoublesReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/CDF.spec.ts b/packages/bloom/lib/commands/t-digest/CDF.spec.ts new file mode 100644 index 0000000000..36d3564f62 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/CDF.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './CDF'; + +describe('TDIGEST.CDF', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.CDF', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.cdf', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.cdf('key', [1]) + ]); + + assert.deepEqual(reply, [NaN]); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/CDF.ts b/packages/bloom/lib/commands/t-digest/CDF.ts new file mode 100644 index 0000000000..fe7ece59d7 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/CDF.ts @@ -0,0 +1,19 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + values: Array +): RedisCommandArguments { + const args = ['TDIGEST.CDF', key]; + for (const item of values) { + args.push(item.toString()); + } + + return args; +} + +export { transformDoublesReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/CREATE.spec.ts b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts new file mode 100644 index 0000000000..4d329cc81a --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/CREATE.spec.ts @@ -0,0 +1,30 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './CREATE'; + +describe('TDIGEST.CREATE', () => { + describe('transformArguments', () => { + it('without options', () => { + assert.deepEqual( + transformArguments('key'), + ['TDIGEST.CREATE', 'key'] + ); + }); + + it('with COMPRESSION', () => { + assert.deepEqual( + transformArguments('key', { + COMPRESSION: 100 + }), + ['TDIGEST.CREATE', 'key', 'COMPRESSION', '100'] + ); + }); + }); + + testUtils.testWithClient('client.tDigest.create', async client => { + assert.equal( + await client.tDigest.create('key'), + 'OK' + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/CREATE.ts b/packages/bloom/lib/commands/t-digest/CREATE.ts new file mode 100644 index 0000000000..1935d2973d --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/CREATE.ts @@ -0,0 +1,16 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { CompressionOption, pushCompressionArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments( + key: RedisCommandArgument, + options?: CompressionOption +): RedisCommandArguments { + return pushCompressionArgument( + ['TDIGEST.CREATE', key], + options + ); +} + +export declare function transformReply(): 'OK'; diff --git a/packages/bloom/lib/commands/t-digest/INFO.spec.ts b/packages/bloom/lib/commands/t-digest/INFO.spec.ts new file mode 100644 index 0000000000..992fda6ea0 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/INFO.spec.ts @@ -0,0 +1,25 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './INFO'; + +describe('TDIGEST.INFO', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['TDIGEST.INFO', 'key'] + ); + }); + + testUtils.testWithClient('client.tDigest.info', async client => { + await client.tDigest.create('key'); + + const info = await client.tDigest.info('key'); + assert(typeof info.capacity, 'number'); + assert(typeof info.mergedNodes, 'number'); + assert(typeof info.unmergedNodes, 'number'); + assert(typeof info.mergedWeight, 'number'); + assert(typeof info.unmergedWeight, 'number'); + assert(typeof info.totalCompression, 'number'); + assert(typeof info.totalCompression, 'number'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/INFO.ts b/packages/bloom/lib/commands/t-digest/INFO.ts new file mode 100644 index 0000000000..44d2083524 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/INFO.ts @@ -0,0 +1,51 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { + return [ + 'TDIGEST.INFO', + key + ]; +} + +type InfoRawReply = [ + 'Compression', + number, + 'Capacity', + number, + 'Merged nodes', + number, + 'Unmerged nodes', + number, + 'Merged weight', + string, + 'Unmerged weight', + string, + 'Total compressions', + number +]; + +interface InfoReply { + comperssion: number; + capacity: number; + mergedNodes: number; + unmergedNodes: number; + mergedWeight: number; + unmergedWeight: number; + totalCompression: number; +} + +export function transformReply(reply: InfoRawReply): InfoReply { + return { + comperssion: reply[1], + capacity: reply[3], + mergedNodes: reply[5], + unmergedNodes: reply[7], + mergedWeight: Number(reply[9]), + unmergedWeight: Number(reply[11]), + totalCompression: reply[13] + }; +} \ No newline at end of file diff --git a/packages/bloom/lib/commands/t-digest/MAX.spec.ts b/packages/bloom/lib/commands/t-digest/MAX.spec.ts new file mode 100644 index 0000000000..bf850cbfd8 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MAX.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments, transformReply } from './MAX'; + +describe('TDIGEST.MAX', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['TDIGEST.MAX', 'key'] + ); + }); + + testUtils.testWithClient('client.tDigest.max', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.max('key') + ]); + + assert.deepEqual(reply, NaN); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/MAX.ts b/packages/bloom/lib/commands/t-digest/MAX.ts new file mode 100644 index 0000000000..90c42ec606 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MAX.ts @@ -0,0 +1,14 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { + return [ + 'TDIGEST.MAX', + key + ]; +} + +export { transformDoubleReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/MERGE.spec.ts b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts new file mode 100644 index 0000000000..1205cdd921 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MERGE.spec.ts @@ -0,0 +1,50 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments, transformReply } from './MERGE'; + +describe('TDIGEST.MERGE', () => { + describe('transformArguments', () => { + describe('srcKeys', () => { + it('string', () => { + assert.deepEqual( + transformArguments('dest', 'src'), + ['TDIGEST.MERGE', 'dest', '1', 'src'] + ); + }); + + it('Array', () => { + assert.deepEqual( + transformArguments('dest', ['1', '2']), + ['TDIGEST.MERGE', 'dest', '2', '1', '2'] + ); + }); + }); + + it('with COMPRESSION', () => { + assert.deepEqual( + transformArguments('dest', 'src', { + COMPRESSION: 100 + }), + ['TDIGEST.MERGE', 'dest', '1', 'src', 'COMPRESSION', '100'] + ); + }); + + it('with OVERRIDE', () => { + assert.deepEqual( + transformArguments('dest', 'src', { + OVERRIDE: true + }), + ['TDIGEST.MERGE', 'dest', '1', 'src', 'OVERRIDE'] + ); + }); + }); + + testUtils.testWithClient('client.tDigest.merge', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('src'), + client.tDigest.merge('dest', 'src') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/MERGE.ts b/packages/bloom/lib/commands/t-digest/MERGE.ts new file mode 100644 index 0000000000..5119d0b9e1 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MERGE.ts @@ -0,0 +1,30 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import { pushVerdictArgument } from '@redis/client/dist/lib/commands/generic-transformers'; +import { CompressionOption, pushCompressionArgument } from '.'; + +export const FIRST_KEY_INDEX = 1; + +interface MergeOptions extends CompressionOption { + OVERRIDE?: boolean; +} + +export function transformArguments( + destKey: RedisCommandArgument, + srcKeys: RedisCommandArgument | Array, + options?: MergeOptions +): RedisCommandArguments { + const args = pushVerdictArgument( + ['TDIGEST.MERGE', destKey], + srcKeys + ); + + pushCompressionArgument(args, options); + + if (options?.OVERRIDE) { + args.push('OVERRIDE'); + } + + return args; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/bloom/lib/commands/t-digest/MIN.spec.ts b/packages/bloom/lib/commands/t-digest/MIN.spec.ts new file mode 100644 index 0000000000..d48deaca7f --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MIN.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments, transformReply } from './MIN'; + +describe('TDIGEST.MIN', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['TDIGEST.MIN', 'key'] + ); + }); + + testUtils.testWithClient('client.tDigest.min', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.min('key') + ]); + + assert.equal(reply, NaN); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/MIN.ts b/packages/bloom/lib/commands/t-digest/MIN.ts new file mode 100644 index 0000000000..d8be8722b6 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/MIN.ts @@ -0,0 +1,14 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { + return [ + 'TDIGEST.MIN', + key + ]; +} + +export { transformDoubleReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts new file mode 100644 index 0000000000..7790debf0d --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.spec.ts @@ -0,0 +1,24 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './QUANTILE'; + +describe('TDIGEST.QUANTILE', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.QUANTILE', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.quantile', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.quantile('key', [1]) + ]); + + assert.deepEqual( + reply, + [NaN] + ); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/QUANTILE.ts b/packages/bloom/lib/commands/t-digest/QUANTILE.ts new file mode 100644 index 0000000000..2289ffc6f5 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/QUANTILE.ts @@ -0,0 +1,23 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + quantiles: Array +): RedisCommandArguments { + const args = [ + 'TDIGEST.QUANTILE', + key + ]; + + for (const quantile of quantiles) { + args.push(quantile.toString()); + } + + return args; +} + +export { transformDoublesReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/RANK.spec.ts b/packages/bloom/lib/commands/t-digest/RANK.spec.ts new file mode 100644 index 0000000000..258bedf349 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/RANK.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './RANK'; + +describe('TDIGEST.RANK', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.RANK', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.rank', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.rank('key', [1]) + ]); + + assert.deepEqual(reply, [-2]); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/RANK.ts b/packages/bloom/lib/commands/t-digest/RANK.ts new file mode 100644 index 0000000000..1a6c84bbd4 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/RANK.ts @@ -0,0 +1,19 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + values: Array +): RedisCommandArguments { + const args = ['TDIGEST.RANK', key]; + for (const item of values) { + args.push(item.toString()); + } + + return args; +} + +export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/t-digest/RESET.spec.ts b/packages/bloom/lib/commands/t-digest/RESET.spec.ts new file mode 100644 index 0000000000..036fbebc8c --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/RESET.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './RESET'; + +describe('TDIGEST.RESET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key'), + ['TDIGEST.RESET', 'key'] + ); + }); + + testUtils.testWithClient('client.tDigest.reset', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.reset('key') + ]); + + assert.equal(reply, 'OK'); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/RESET.ts b/packages/bloom/lib/commands/t-digest/RESET.ts new file mode 100644 index 0000000000..6c700e6b93 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/RESET.ts @@ -0,0 +1,9 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export function transformArguments(key: RedisCommandArgument): RedisCommandArguments { + return ['TDIGEST.RESET', key]; +} + +export declare function transformReply(): 'OK'; diff --git a/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts new file mode 100644 index 0000000000..21d16661df --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/REVRANK.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments } from './REVRANK'; + +describe('TDIGEST.REVRANK', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', [1, 2]), + ['TDIGEST.REVRANK', 'key', '1', '2'] + ); + }); + + testUtils.testWithClient('client.tDigest.revRank', async client => { + const [ , reply ] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.revRank('key', [1]) + ]); + + assert.deepEqual(reply, [-2]); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/REVRANK.ts b/packages/bloom/lib/commands/t-digest/REVRANK.ts new file mode 100644 index 0000000000..a246505277 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/REVRANK.ts @@ -0,0 +1,19 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + values: Array +): RedisCommandArguments { + const args = ['TDIGEST.REVRANK', key]; + for (const item of values) { + args.push(item.toString()); + } + + return args; +} + +export declare function transformReply(): Array; diff --git a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts new file mode 100644 index 0000000000..dd07f325c8 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.spec.ts @@ -0,0 +1,21 @@ +import { strict as assert } from 'assert'; +import testUtils, { GLOBAL } from '../../test-utils'; +import { transformArguments, transformReply } from './TRIMMED_MEAN'; + +describe('TDIGEST.RESET', () => { + it('transformArguments', () => { + assert.deepEqual( + transformArguments('key', 0, 1), + ['TDIGEST.TRIMMED_MEAN', 'key', '0', '1'] + ); + }); + + testUtils.testWithClient('client.tDigest.trimmedMean', async client => { + const [, reply] = await Promise.all([ + client.tDigest.create('key'), + client.tDigest.trimmedMean('key', 0, 1) + ]); + + assert.equal(reply, NaN); + }, GLOBAL.SERVERS.OPEN); +}); diff --git a/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts new file mode 100644 index 0000000000..6de80ba7c7 --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/TRIMMED_MEAN.ts @@ -0,0 +1,20 @@ +import { RedisCommandArgument, RedisCommandArguments } from '@redis/client/dist/lib/commands'; + +export const FIRST_KEY_INDEX = 1; + +export const IS_READ_ONLY = true; + +export function transformArguments( + key: RedisCommandArgument, + lowCutPercentile: number, + highCutPercentile: number +): RedisCommandArguments { + return [ + 'TDIGEST.TRIMMED_MEAN', + key, + lowCutPercentile.toString(), + highCutPercentile.toString() + ]; +} + +export { transformDoubleReply as transformReply } from '.'; diff --git a/packages/bloom/lib/commands/t-digest/index.spec.ts b/packages/bloom/lib/commands/t-digest/index.spec.ts new file mode 100644 index 0000000000..5bef6df04b --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/index.spec.ts @@ -0,0 +1,55 @@ +import { strict as assert } from 'assert'; +import { pushCompressionArgument, transformDoubleReply, transformDoublesReply } from '.'; + +describe('pushCompressionArgument', () => { + it('undefined', () => { + assert.deepEqual( + pushCompressionArgument([]), + [] + ); + }); + + it('100', () => { + assert.deepEqual( + pushCompressionArgument([], { COMPRESSION: 100 }), + ['COMPRESSION', '100'] + ); + }); +}); + +describe('transformDoubleReply', () => { + it('inf', () => { + assert.equal( + transformDoubleReply('inf'), + Infinity + ); + }); + + it('-inf', () => { + assert.equal( + transformDoubleReply('-inf'), + -Infinity + ); + }); + + it('nan', () => { + assert.equal( + transformDoubleReply('nan'), + NaN + ); + }); + + it('0', () => { + assert.equal( + transformDoubleReply('0'), + 0 + ); + }); +}); + +it('transformDoublesReply', () => { + assert.deepEqual( + transformDoublesReply(['inf', '-inf', 'nan', '0']), + [Infinity, -Infinity, NaN, 0] + ); +}); diff --git a/packages/bloom/lib/commands/t-digest/index.ts b/packages/bloom/lib/commands/t-digest/index.ts new file mode 100644 index 0000000000..da3b37464d --- /dev/null +++ b/packages/bloom/lib/commands/t-digest/index.ts @@ -0,0 +1,81 @@ +import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; +import * as ADD from './ADD'; +import * as BYRANK from './BYRANK'; +import * as BYREVRANK from './BYREVRANK'; +import * as CDF from './CDF'; +import * as CREATE from './CREATE'; +import * as INFO from './INFO'; +import * as MAX from './MAX'; +import * as MERGE from './MERGE'; +import * as MIN from './MIN'; +import * as QUANTILE from './QUANTILE'; +import * as RANK from './RANK'; +import * as RESET from './RESET'; +import * as REVRANK from './REVRANK'; +import * as TRIMMED_MEAN from './TRIMMED_MEAN'; + +export default { + ADD, + add: ADD, + BYRANK, + byRank: BYRANK, + BYREVRANK, + byRevRank: BYREVRANK, + CDF, + cdf: CDF, + CREATE, + create: CREATE, + INFO, + info: INFO, + MAX, + max: MAX, + MERGE, + merge: MERGE, + MIN, + min: MIN, + QUANTILE, + quantile: QUANTILE, + RANK, + rank: RANK, + RESET, + reset: RESET, + REVRANK, + revRank: REVRANK, + TRIMMED_MEAN, + trimmedMean: TRIMMED_MEAN +}; + +export interface CompressionOption { + COMPRESSION?: number; +} + +export function pushCompressionArgument( + args: RedisCommandArguments, + options?: CompressionOption +): RedisCommandArguments { + if (options?.COMPRESSION) { + args.push('COMPRESSION', options.COMPRESSION.toString()); + } + + return args; +} + +export function transformDoubleReply(reply: string): number { + switch (reply) { + case 'inf': + return Infinity; + + case '-inf': + return -Infinity; + + case 'nan': + return NaN; + + default: + return parseFloat(reply); + } +} + +export function transformDoublesReply(reply: Array): Array { + return reply.map(transformDoubleReply); +} diff --git a/packages/bloom/lib/test-utils.ts b/packages/bloom/lib/test-utils.ts index 4bcebad93a..a2e059b3b9 100644 --- a/packages/bloom/lib/test-utils.ts +++ b/packages/bloom/lib/test-utils.ts @@ -4,7 +4,7 @@ import RedisBloomModules from '.'; export default new TestUtils({ dockerImageName: 'redislabs/rebloom', dockerImageVersionArgument: 'redisbloom-version', - defaultDockerVersion: '2.2.9' + defaultDockerVersion: 'edge' }); export const GLOBAL = { diff --git a/packages/test-utils/lib/index.ts b/packages/test-utils/lib/index.ts index 3e33971fdd..7b9494c8d6 100644 --- a/packages/test-utils/lib/index.ts +++ b/packages/test-utils/lib/index.ts @@ -42,24 +42,32 @@ interface Version { } export default class TestUtils { + static #parseVersionNumber(version: string): Array { + if (version === 'edge') return [Infinity]; + + const dashIndex = version.indexOf('-'); + return (dashIndex === -1 ? version : version.substring(0, dashIndex)) + .split('.') + .map(x => { + const value = Number(x); + if (Number.isNaN(value)) { + throw new TypeError(`${version} is not a valid redis version`); + } + + return value; + }); + } + static #getVersion(argumentName: string, defaultVersion: string): Version { return yargs(hideBin(process.argv)) .option(argumentName, { type: 'string', default: defaultVersion }) - .coerce(argumentName, (arg: string) => { - const indexOfDash = arg.indexOf('-'); + .coerce(argumentName, (version: string) => { return { - string: arg, - numbers: (indexOfDash === -1 ? arg : arg.substring(0, indexOfDash)).split('.').map(x => { - const value = Number(x); - if (Number.isNaN(value)) { - throw new TypeError(`${arg} is not a valid redis version`); - } - - return value; - }) + string: version, + numbers: TestUtils.#parseVersionNumber(version) }; }) .demandOption(argumentName)