1
0
mirror of https://github.com/redis/node-redis.git synced 2025-08-07 13:22:56 +03:00

time-series

This commit is contained in:
Leibale
2023-07-11 13:11:13 -04:00
parent c515bc9571
commit 54c3a66c72
32 changed files with 879 additions and 933 deletions

View File

@@ -1,7 +1,7 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import ADD from './ADD'; import ADD from './ADD';
import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.'; import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.';
describe('TS.ADD', () => { describe('TS.ADD', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
@@ -24,7 +24,7 @@ describe('TS.ADD', () => {
it('with ENCODING', () => { it('with ENCODING', () => {
assert.deepEqual( assert.deepEqual(
ADD.transformArguments('key', '*', 1, { ADD.transformArguments('key', '*', 1, {
ENCODING: TimeSeriesEncoding.UNCOMPRESSED ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED
}), }),
['TS.ADD', 'key', '*', '1', 'ENCODING', 'UNCOMPRESSED'] ['TS.ADD', 'key', '*', '1', 'ENCODING', 'UNCOMPRESSED']
); );
@@ -42,7 +42,7 @@ describe('TS.ADD', () => {
it('with ON_DUPLICATE', () => { it('with ON_DUPLICATE', () => {
assert.deepEqual( assert.deepEqual(
ADD.transformArguments('key', '*', 1, { ADD.transformArguments('key', '*', 1, {
ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK
}), }),
['TS.ADD', 'key', '*', '1', 'ON_DUPLICATE', 'BLOCK'] ['TS.ADD', 'key', '*', '1', 'ON_DUPLICATE', 'BLOCK']
); );
@@ -61,9 +61,9 @@ describe('TS.ADD', () => {
assert.deepEqual( assert.deepEqual(
ADD.transformArguments('key', '*', 1, { ADD.transformArguments('key', '*', 1, {
RETENTION: 1, RETENTION: 1,
ENCODING: TimeSeriesEncoding.UNCOMPRESSED, ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
CHUNK_SIZE: 1, CHUNK_SIZE: 1,
ON_DUPLICATE: TimeSeriesDuplicatePolicies.BLOCK, ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
LABELS: { label: 'value' } LABELS: { label: 'value' }
}), }),
['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']

View File

@@ -1,7 +1,7 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { TimeSeriesDuplicatePolicies } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import ALTER from './ALTER'; import ALTER from './ALTER';
import { TIME_SERIES_DUPLICATE_POLICIES } from '.';
describe('TS.ALTER', () => { describe('TS.ALTER', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
@@ -33,7 +33,7 @@ describe('TS.ALTER', () => {
it('with DUPLICATE_POLICY', () => { it('with DUPLICATE_POLICY', () => {
assert.deepEqual( assert.deepEqual(
ALTER.transformArguments('key', { ALTER.transformArguments('key', {
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK
}), }),
['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK'] ['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK']
); );
@@ -53,7 +53,7 @@ describe('TS.ALTER', () => {
ALTER.transformArguments('key', { ALTER.transformArguments('key', {
RETENTION: 1, RETENTION: 1,
CHUNK_SIZE: 1, CHUNK_SIZE: 1,
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
LABELS: { label: 'value' } LABELS: { label: 'value' }
}), }),
['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']
@@ -62,11 +62,11 @@ describe('TS.ALTER', () => {
}); });
testUtils.testWithClient('client.ts.alter', async client => { testUtils.testWithClient('client.ts.alter', async client => {
await client.ts.create('key'); const [, reply] = await Promise.all([
client.ts.create('key'),
client.ts.alter('key', { RETENTION: 1 })
]);
assert.equal( assert.equal(reply, 'OK');
await client.ts.alter('key', { RETENTION: 1 }),
'OK'
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,12 +1,8 @@
import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { TsCreateOptions } from './CREATE';
import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument } from '.';
export interface TsAlterOptions { export type TsAlterOptions = Pick<TsCreateOptions, 'RETENTION' | 'CHUNK_SIZE' | 'DUPLICATE_POLICY' | 'LABELS'>;
RETENTION?: number;
CHUNK_SIZE?: number;
DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies;
LABELS?: Labels;
}
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,

View File

@@ -1,9 +1,9 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import CREATE from './CREATE'; import CREATE from './CREATE';
import { TIME_SERIES_ENCODING, TIME_SERIES_DUPLICATE_POLICIES } from '.';
describe('CREATE', () => { describe('TS.CREATE', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
@@ -24,7 +24,7 @@ describe('CREATE', () => {
it('with ENCODING', () => { it('with ENCODING', () => {
assert.deepEqual( assert.deepEqual(
CREATE.transformArguments('key', { CREATE.transformArguments('key', {
ENCODING: TimeSeriesEncoding.UNCOMPRESSED ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED
}), }),
['TS.CREATE', 'key', 'ENCODING', 'UNCOMPRESSED'] ['TS.CREATE', 'key', 'ENCODING', 'UNCOMPRESSED']
); );
@@ -42,7 +42,7 @@ describe('CREATE', () => {
it('with DUPLICATE_POLICY', () => { it('with DUPLICATE_POLICY', () => {
assert.deepEqual( assert.deepEqual(
CREATE.transformArguments('key', { CREATE.transformArguments('key', {
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK
}), }),
['TS.CREATE', 'key', 'DUPLICATE_POLICY', 'BLOCK'] ['TS.CREATE', 'key', 'DUPLICATE_POLICY', 'BLOCK']
); );
@@ -61,9 +61,9 @@ describe('CREATE', () => {
assert.deepEqual( assert.deepEqual(
CREATE.transformArguments('key', { CREATE.transformArguments('key', {
RETENTION: 1, RETENTION: 1,
ENCODING: TimeSeriesEncoding.UNCOMPRESSED, ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
CHUNK_SIZE: 1, CHUNK_SIZE: 1,
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK, DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
LABELS: { label: 'value' } LABELS: { label: 'value' }
}), }),
['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']

View File

@@ -1,14 +1,14 @@
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
import { import {
pushRetentionArgument, pushRetentionArgument,
TimeSeriesEncoding, TimeSeriesEncoding,
pushEncodingArgument, pushEncodingArgument,
pushChunkSizeArgument, pushChunkSizeArgument,
TimeSeriesDuplicatePolicies, TimeSeriesDuplicatePolicies,
pushDuplicatePolicy,
Labels, Labels,
pushLabelsArgument, pushLabelsArgument
pushDuplicatePolicy
} from '.'; } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface TsCreateOptions { export interface TsCreateOptions {
RETENTION?: number; RETENTION?: number;

View File

@@ -1,34 +1,31 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { TimeSeriesAggregationType } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import CREATERULE from './CREATERULE'; import CREATERULE, { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
describe('CREATERULE', () => { describe('TS.CREATERULE', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1), CREATERULE.transformArguments('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1),
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1'] ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1']
); );
}); });
it('with alignTimestamp', () => { it('with alignTimestamp', () => {
assert.deepEqual( assert.deepEqual(
CREATERULE.transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1, 1), CREATERULE.transformArguments('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1, 1),
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1'] ['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1']
); );
}); });
}); });
testUtils.testWithClient('client.ts.createRule', async client => { testUtils.testWithClient('client.ts.createRule', async client => {
await Promise.all([ const [, , reply] = await Promise.all([
client.ts.create('source'), client.ts.create('source'),
client.ts.create('destination') client.ts.create('destination'),
client.ts.createRule('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1)
]); ]);
assert.equal( assert.equal(reply, 'OK');
await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1),
'OK'
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,6 +1,23 @@
import { TimeSeriesAggregationType } from '.';
import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisArgument, SimpleStringReply, Command } from '@redis/client/dist/lib/RESP/types';
export const TIME_SERIES_AGGREGATION_TYPE = {
AVG: 'AVG',
FIRST: 'FIRST',
LAST: 'LAST',
MIN: 'MIN',
MAX: 'MAX',
SUM: 'SUM',
RANGE: 'RANGE',
COUNT: 'COUNT',
STD_P: 'STD.P',
STD_S: 'STD.S',
VAR_P: 'VAR.P',
VAR_S: 'VAR.S',
TWA: 'TWA'
} as const;
export type TimeSeriesAggregationType = typeof TIME_SERIES_AGGREGATION_TYPE[keyof typeof TIME_SERIES_AGGREGATION_TYPE];
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false, IS_READ_ONLY: false,
@@ -20,7 +37,7 @@ export default {
bucketDuration.toString() bucketDuration.toString()
]; ];
if (alignTimestamp) { if (alignTimestamp !== undefined) {
args.push(alignTimestamp.toString()); args.push(alignTimestamp.toString());
} }

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DECRBY from './DECRBY'; import DECRBY from './DECRBY';
describe('DECRBY', () => { describe('TS.DECRBY', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
@@ -72,10 +72,8 @@ describe('DECRBY', () => {
testUtils.testWithClient('client.ts.decrBy', async client => { testUtils.testWithClient('client.ts.decrBy', async client => {
assert.equal( assert.equal(
await client.ts.decrBy('key', 1, { typeof await client.ts.decrBy('key', 1),
TIMESTAMP: 0 'number'
}),
0
); );
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,11 +1,9 @@
import { IncrDecrOptions, transformIncrDecrArguments } from '.'; import { Command } from '@redis/client/dist/lib/RESP/types';
import { RedisArgument, Command, NumberReply } from '@redis/client/dist/lib/RESP/types'; import INCRBY, { transformIncrByArguments } from './INCRBY';
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: INCRBY.FIRST_KEY_INDEX,
IS_READ_ONLY: false, IS_READ_ONLY: INCRBY.IS_READ_ONLY,
transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { transformArguments: transformIncrByArguments.bind(undefined, 'TS.DECRBY'),
return transformIncrDecrArguments('TS.DECRBY', key, value, options); transformReply: INCRBY.transformReply
},
transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command; } as const satisfies Command;

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DEL from './DEL'; import DEL from './DEL';
describe('DEL', () => { describe('TS.DEL', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
DEL.transformArguments('key', '-', '+'), DEL.transformArguments('key', '-', '+'),
@@ -11,11 +11,11 @@ describe('DEL', () => {
}); });
testUtils.testWithClient('client.ts.del', async client => { testUtils.testWithClient('client.ts.del', async client => {
await client.ts.create('key'); const [, reply] = await Promise.all([
client.ts.create('key'),
client.ts.del('key', '-', '+')
]);
assert.equal( assert.equal(reply, 0);
await client.ts.del('key', '-', '+'),
0
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,9 +1,9 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import { TimeSeriesAggregationType } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import DELETERULE from './DELETERULE'; import DELETERULE from './DELETERULE';
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
describe('DELETERULE', () => { describe('TS.DELETERULE', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
DELETERULE.transformArguments('source', 'destination'), DELETERULE.transformArguments('source', 'destination'),
@@ -12,15 +12,13 @@ describe('DELETERULE', () => {
}); });
testUtils.testWithClient('client.ts.deleteRule', async client => { testUtils.testWithClient('client.ts.deleteRule', async client => {
await Promise.all([ const [, , , reply] = await Promise.all([
client.ts.create('source'), client.ts.create('source'),
client.ts.create('destination'), client.ts.create('destination'),
client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1) client.ts.createRule('source', 'destination', TIME_SERIES_AGGREGATION_TYPE.AVG, 1),
client.ts.deleteRule('source', 'destination')
]); ]);
assert.equal( assert.equal(reply, 'OK');
await client.ts.deleteRule('source', 'destination'),
'OK'
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import GET from './GET'; import GET from './GET';
describe('GET', () => { describe('TS.GET', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
@@ -23,24 +23,24 @@ describe('GET', () => {
describe('client.ts.get', () => { describe('client.ts.get', () => {
testUtils.testWithClient('null', async client => { testUtils.testWithClient('null', async client => {
await client.ts.create('key'); const [, reply] = await Promise.all([
client.ts.create('key'),
client.ts.get('key')
]);
assert.equal( assert.equal(reply, null);
await client.ts.get('key'),
null
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
testUtils.testWithClient('with samples', async client => { testUtils.testWithClient('with sample', async client => {
await client.ts.add('key', 0, 1); const [, reply] = await Promise.all([
client.ts.add('key', 0, 1),
client.ts.get('key')
]);
assert.deepEqual( assert.deepEqual(reply, {
await client.ts.get('key'), timestamp: 0,
{ value: 1
timestamp: 0, });
value: 1
}
);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });
}); });

View File

@@ -1,5 +1,4 @@
import { RedisArgument, TuplesReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisArgument, TuplesReply, NumberReply, DoubleReply, Resp2Reply, Command } from '@redis/client/dist/lib/RESP/types';
import { pushLatestArgument } from '.';
export interface TsGetOptions { export interface TsGetOptions {
LATEST?: boolean; LATEST?: boolean;
@@ -11,7 +10,13 @@ export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: true, IS_READ_ONLY: true,
transformArguments(key: RedisArgument, options?: TsGetOptions) { transformArguments(key: RedisArgument, options?: TsGetOptions) {
return pushLatestArgument(['TS.GET', key], options?.LATEST); const args = ['TS.GET', key];
if (options?.LATEST) {
args.push('LATEST');
}
return args;
}, },
transformReply: { transformReply: {
2(reply: Resp2Reply<TsGetReply>) { 2(reply: Resp2Reply<TsGetReply>) {

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import INCRBY from './INCRBY'; import INCRBY from './INCRBY';
describe('INCRBY', () => { describe('TS.INCRBY', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(
@@ -82,10 +82,8 @@ describe('INCRBY', () => {
testUtils.testWithClient('client.ts.incrBy', async client => { testUtils.testWithClient('client.ts.incrBy', async client => {
assert.equal( assert.equal(
await client.ts.incrBy('key', 1, { typeof await client.ts.incrBy('key', 1),
TIMESTAMP: 0 'number'
}),
0
); );
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,11 +1,46 @@
import { IncrDecrOptions, transformIncrDecrArguments } from '.';
import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; import { RedisArgument, NumberReply, Command } from '@redis/client/dist/lib/RESP/types';
import { Timestamp, transformTimestampArgument, pushRetentionArgument, pushChunkSizeArgument, Labels, pushLabelsArgument } from '.';
export interface TsIncrByOptions {
TIMESTAMP?: Timestamp;
RETENTION?: number;
UNCOMPRESSED?: boolean;
CHUNK_SIZE?: number;
LABELS?: Labels;
}
export function transformIncrByArguments(
command: RedisArgument,
key: RedisArgument,
value: number,
options?: TsIncrByOptions
) {
const args = [
command,
key,
value.toString()
];
if (options?.TIMESTAMP !== undefined && options?.TIMESTAMP !== null) {
args.push('TIMESTAMP', transformTimestampArgument(options.TIMESTAMP));
}
pushRetentionArgument(args, options?.RETENTION);
if (options?.UNCOMPRESSED) {
args.push('UNCOMPRESSED');
}
pushChunkSizeArgument(args, options?.CHUNK_SIZE);
pushLabelsArgument(args, options?.LABELS);
return args;
}
export default { export default {
FIRST_KEY_INDEX: 1, FIRST_KEY_INDEX: 1,
IS_READ_ONLY: false, IS_READ_ONLY: false,
transformArguments(key: RedisArgument, value: number, options?: IncrDecrOptions) { transformArguments: transformIncrByArguments.bind(undefined, 'TS.INCRBY'),
return transformIncrDecrArguments('TS.INCRBY', key, value, options);
},
transformReply: undefined as unknown as () => NumberReply transformReply: undefined as unknown as () => NumberReply
} as const satisfies Command; } as const satisfies Command;

View File

@@ -3,7 +3,7 @@ import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { InfoReply, transformArguments } from './INFO'; import { InfoReply, transformArguments } from './INFO';
describe('INFO', () => { describe('TS.INFO', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key'), transformArguments('key'),

View File

@@ -4,7 +4,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { assertInfo } from './INFO.spec'; import { assertInfo } from './INFO.spec';
import { transformArguments } from './INFO_DEBUG'; import { transformArguments } from './INFO_DEBUG';
describe('INFO_DEBUG', () => { describe('TS.INFO_DEBUG', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key'), transformArguments('key'),

View File

@@ -1,8 +1,9 @@
import { strict as assert } from 'assert'; import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import MADD from './MADD'; import MADD from './MADD';
import { SimpleError } from '@redis/client/lib/errors';
describe('MADD', () => { describe.only('TS.MADD', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
MADD.transformArguments([{ MADD.transformArguments([{
@@ -18,22 +19,23 @@ describe('MADD', () => {
); );
}); });
// Should we check empty array?
testUtils.testWithClient('client.ts.mAdd', async client => { testUtils.testWithClient('client.ts.mAdd', async client => {
await client.ts.create('key'); const [, reply] = await Promise.all([
client.ts.create('key'),
assert.deepEqual( client.ts.mAdd([{
await client.ts.mAdd([{
key: 'key', key: 'key',
timestamp: 0, timestamp: 0,
value: 0 value: 1
}, { }, {
key: 'key', key: 'key',
timestamp: 1, timestamp: 0,
value: 1 value: 1
}]), }])
[0, 1] ]);
);
assert.ok(Array.isArray(reply));
assert.equal(reply.length, 2);
assert.equal(reply[0], 0);
assert.ok(reply[1] instanceof SimpleError);
}, GLOBAL.SERVERS.OPEN); }, GLOBAL.SERVERS.OPEN);
}); });

View File

@@ -1,5 +1,5 @@
import { Timestamp, transformTimestampArgument } from '.'; import { Timestamp, transformTimestampArgument } from '.';
import { ArrayReply, NumberReply, Command } from '@redis/client/dist/lib/RESP/types'; import { ArrayReply, NumberReply, SimpleErrorReply, Command } from '@redis/client/dist/lib/RESP/types';
export interface TsMAddSample { export interface TsMAddSample {
key: string; key: string;
@@ -23,5 +23,5 @@ export default {
return args; return args;
}, },
transformReply: undefined as unknown as () => ArrayReply<NumberReply> transformReply: undefined as unknown as () => ArrayReply<NumberReply | SimpleErrorReply>
} as const satisfies Command; } as const satisfies Command;

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MGET'; import { transformArguments } from './MGET';
describe('MGET', () => { describe('TS.MGET', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MGET_WITHLABELS'; import { transformArguments } from './MGET_WITHLABELS';
describe('MGET_WITHLABELS', () => { describe('TS.MGET_WITHLABELS', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MRANGE'; import { transformArguments } from './MRANGE';
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
describe('MRANGE', () => { describe('TS.MRANGE', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('-', '+', 'label=value', { transformArguments('-', '+', 'label=value', {

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MRANGE_WITHLABELS'; import { transformArguments } from './MRANGE_WITHLABELS';
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
describe('MRANGE_WITHLABELS', () => { describe('TS.MRANGE_WITHLABELS', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('-', '+', 'label=value', { transformArguments('-', '+', 'label=value', {

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MREVRANGE'; import { transformArguments } from './MREVRANGE';
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
describe('MREVRANGE', () => { describe('TS.MREVRANGE', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('-', '+', 'label=value', { transformArguments('-', '+', 'label=value', {

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './MREVRANGE_WITHLABELS'; import { transformArguments } from './MREVRANGE_WITHLABELS';
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.'; import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
describe('MREVRANGE_WITHLABELS', () => { describe('TS.MREVRANGE_WITHLABELS', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('-', '+', 'label=value', { transformArguments('-', '+', 'label=value', {

View File

@@ -2,7 +2,7 @@ import { strict as assert } from 'assert';
import testUtils, { GLOBAL } from '../test-utils'; import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './QUERYINDEX'; import { transformArguments } from './QUERYINDEX';
describe('QUERYINDEX', () => { describe('TS.QUERYINDEX', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('single filter', () => { it('single filter', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './RANGE'; import { transformArguments } from './RANGE';
import { TimeSeriesAggregationType } from '.'; import { TimeSeriesAggregationType } from '.';
describe('RANGE', () => { describe('TS.RANGE', () => {
it('transformArguments', () => { it('transformArguments', () => {
assert.deepEqual( assert.deepEqual(
transformArguments('key', '-', '+', { transformArguments('key', '-', '+', {

View File

@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
import { transformArguments } from './REVRANGE'; import { transformArguments } from './REVRANGE';
import { TimeSeriesAggregationType } from '.'; import { TimeSeriesAggregationType } from '.';
describe('REVRANGE', () => { describe('TS.REVRANGE', () => {
describe('transformArguments', () => { describe('transformArguments', () => {
it('without options', () => { it('without options', () => {
assert.deepEqual( assert.deepEqual(

View File

@@ -1,439 +1,439 @@
import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; // import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
import { strict as assert } from 'assert'; // import { strict as assert } from 'assert';
import { // import {
transformTimestampArgument, // transformTimestampArgument,
pushRetentionArgument, // pushRetentionArgument,
TimeSeriesEncoding, // TimeSeriesEncoding,
pushEncodingArgument, // pushEncodingArgument,
pushChunkSizeArgument, // pushChunkSizeArgument,
pushDuplicatePolicy, // pushDuplicatePolicy,
pushLabelsArgument, // pushLabelsArgument,
transformIncrDecrArguments, // transformIncrDecrArguments,
transformSampleReply, // transformSampleReply,
TimeSeriesAggregationType, // TimeSeriesAggregationType,
pushRangeArguments, // pushRangeArguments,
pushMRangeGroupByArguments, // pushMRangeGroupByArguments,
TimeSeriesReducers, // TimeSeriesReducers,
pushFilterArgument, // pushFilterArgument,
pushMRangeArguments, // pushMRangeArguments,
pushWithLabelsArgument, // pushWithLabelsArgument,
pushMRangeWithLabelsArguments, // pushMRangeWithLabelsArguments,
transformRangeReply, // transformRangeReply,
transformMRangeReply, // transformMRangeReply,
transformMRangeWithLabelsReply, // transformMRangeWithLabelsReply,
TimeSeriesDuplicatePolicies, // TimeSeriesDuplicatePolicies,
pushLatestArgument, // pushLatestArgument,
TimeSeriesBucketTimestamp // TimeSeriesBucketTimestamp
} from '.'; // } from '.';
describe('transformTimestampArgument', () => { // describe('transformTimestampArgument', () => {
it('number', () => { // it('number', () => {
assert.equal( // assert.equal(
transformTimestampArgument(0), // transformTimestampArgument(0),
'0' // '0'
); // );
}); // });
it('Date', () => { // it('Date', () => {
assert.equal( // assert.equal(
transformTimestampArgument(new Date(0)), // transformTimestampArgument(new Date(0)),
'0' // '0'
); // );
}); // });
it('string', () => { // it('string', () => {
assert.equal( // assert.equal(
transformTimestampArgument('*'), // transformTimestampArgument('*'),
'*' // '*'
); // );
}); // });
}); // });
function testOptionalArgument(fn: (args: RedisCommandArguments) => unknown): void { // function testOptionalArgument(fn: (args: RedisCommandArguments) => unknown): void {
it('undefined', () => { // it('undefined', () => {
assert.deepEqual( // assert.deepEqual(
fn([]), // fn([]),
[] // []
); // );
}); // });
} // }
describe('pushRetentionArgument', () => { // describe('pushRetentionArgument', () => {
testOptionalArgument(pushRetentionArgument); // testOptionalArgument(pushRetentionArgument);
it('number', () => { // it('number', () => {
assert.deepEqual( // assert.deepEqual(
pushRetentionArgument([], 1), // pushRetentionArgument([], 1),
['RETENTION', '1'] // ['RETENTION', '1']
); // );
}); // });
}); // });
describe('pushEncodingArgument', () => { // describe('pushEncodingArgument', () => {
testOptionalArgument(pushEncodingArgument); // testOptionalArgument(pushEncodingArgument);
it('UNCOMPRESSED', () => { // it('UNCOMPRESSED', () => {
assert.deepEqual( // assert.deepEqual(
pushEncodingArgument([], TimeSeriesEncoding.UNCOMPRESSED), // pushEncodingArgument([], TimeSeriesEncoding.UNCOMPRESSED),
['ENCODING', 'UNCOMPRESSED'] // ['ENCODING', 'UNCOMPRESSED']
); // );
}); // });
}); // });
describe('pushChunkSizeArgument', () => { // describe('pushChunkSizeArgument', () => {
testOptionalArgument(pushChunkSizeArgument); // testOptionalArgument(pushChunkSizeArgument);
it('number', () => { // it('number', () => {
assert.deepEqual( // assert.deepEqual(
pushChunkSizeArgument([], 1), // pushChunkSizeArgument([], 1),
['CHUNK_SIZE', '1'] // ['CHUNK_SIZE', '1']
); // );
}); // });
}); // });
describe('pushDuplicatePolicy', () => { // describe('pushDuplicatePolicy', () => {
testOptionalArgument(pushDuplicatePolicy); // testOptionalArgument(pushDuplicatePolicy);
it('BLOCK', () => { // it('BLOCK', () => {
assert.deepEqual( // assert.deepEqual(
pushDuplicatePolicy([], TimeSeriesDuplicatePolicies.BLOCK), // pushDuplicatePolicy([], TimeSeriesDuplicatePolicies.BLOCK),
['DUPLICATE_POLICY', 'BLOCK'] // ['DUPLICATE_POLICY', 'BLOCK']
); // );
}); // });
}); // });
describe('pushLabelsArgument', () => { // describe('pushLabelsArgument', () => {
testOptionalArgument(pushLabelsArgument); // testOptionalArgument(pushLabelsArgument);
it("{ label: 'value' }", () => { // it("{ label: 'value' }", () => {
assert.deepEqual( // assert.deepEqual(
pushLabelsArgument([], { label: 'value' }), // pushLabelsArgument([], { label: 'value' }),
['LABELS', 'label', 'value'] // ['LABELS', 'label', 'value']
); // );
}); // });
}); // });
describe('transformIncrDecrArguments', () => { // describe('transformIncrDecrArguments', () => {
it('without options', () => { // it('without options', () => {
assert.deepEqual( // assert.deepEqual(
transformIncrDecrArguments('TS.INCRBY', 'key', 1), // transformIncrDecrArguments('TS.INCRBY', 'key', 1),
['TS.INCRBY', 'key', '1'] // ['TS.INCRBY', 'key', '1']
); // );
}); // });
it('with TIMESTAMP', () => { // it('with TIMESTAMP', () => {
assert.deepEqual( // assert.deepEqual(
transformIncrDecrArguments('TS.INCRBY', 'key', 1, { // transformIncrDecrArguments('TS.INCRBY', 'key', 1, {
TIMESTAMP: '*' // TIMESTAMP: '*'
}), // }),
['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*'] // ['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*']
); // );
}); // });
it('with UNCOMPRESSED', () => { // it('with UNCOMPRESSED', () => {
assert.deepEqual( // assert.deepEqual(
transformIncrDecrArguments('TS.INCRBY', 'key', 1, { // transformIncrDecrArguments('TS.INCRBY', 'key', 1, {
UNCOMPRESSED: true // UNCOMPRESSED: true
}), // }),
['TS.INCRBY', 'key', '1', 'UNCOMPRESSED'] // ['TS.INCRBY', 'key', '1', 'UNCOMPRESSED']
); // );
}); // });
it('with UNCOMPRESSED false', () => { // it('with UNCOMPRESSED false', () => {
assert.deepEqual( // assert.deepEqual(
transformIncrDecrArguments('TS.INCRBY', 'key', 1, { // transformIncrDecrArguments('TS.INCRBY', 'key', 1, {
UNCOMPRESSED: false // UNCOMPRESSED: false
}), // }),
['TS.INCRBY', 'key', '1'] // ['TS.INCRBY', 'key', '1']
); // );
}); // });
}); // });
it('transformSampleReply', () => { // it('transformSampleReply', () => {
assert.deepEqual( // assert.deepEqual(
transformSampleReply([1, '1.1']), // transformSampleReply([1, '1.1']),
{ // {
timestamp: 1, // timestamp: 1,
value: 1.1 // value: 1.1
} // }
); // );
}); // });
describe('pushRangeArguments', () => { // describe('pushRangeArguments', () => {
it('without options', () => { // it('without options', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+'), // pushRangeArguments([], '-', '+'),
['-', '+'] // ['-', '+']
); // );
}); // });
describe('with FILTER_BY_TS', () => { // describe('with FILTER_BY_TS', () => {
it('string', () => { // it('string', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
FILTER_BY_TS: ['ts'] // FILTER_BY_TS: ['ts']
}), // }),
['-', '+', 'FILTER_BY_TS', 'ts'] // ['-', '+', 'FILTER_BY_TS', 'ts']
); // );
}); // });
it('Array', () => { // it('Array', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
FILTER_BY_TS: ['1', '2'] // FILTER_BY_TS: ['1', '2']
}), // }),
['-', '+', 'FILTER_BY_TS', '1', '2'] // ['-', '+', 'FILTER_BY_TS', '1', '2']
); // );
}); // });
}); // });
it('with FILTER_BY_VALUE', () => { // it('with FILTER_BY_VALUE', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
FILTER_BY_VALUE: { // FILTER_BY_VALUE: {
min: 1, // min: 1,
max: 2 // max: 2
} // }
}), // }),
['-', '+', 'FILTER_BY_VALUE', '1', '2'] // ['-', '+', 'FILTER_BY_VALUE', '1', '2']
); // );
}); // });
it('with COUNT', () => { // it('with COUNT', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
COUNT: 1 // COUNT: 1
}), // }),
['-', '+', 'COUNT', '1'] // ['-', '+', 'COUNT', '1']
); // );
}); // });
it('with ALIGN', () => { // it('with ALIGN', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
ALIGN: 1 // ALIGN: 1
}), // }),
['-', '+', 'ALIGN', '1'] // ['-', '+', 'ALIGN', '1']
); // );
}); // });
describe('with AGGREGATION', () => { // describe('with AGGREGATION', () => {
it('without options', () => { // it('without options', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
AGGREGATION: { // AGGREGATION: {
type: TimeSeriesAggregationType.FIRST, // type: TimeSeriesAggregationType.FIRST,
timeBucket: 1 // timeBucket: 1
} // }
}), // }),
['-', '+', 'AGGREGATION', 'FIRST', '1'] // ['-', '+', 'AGGREGATION', 'FIRST', '1']
); // );
}); // });
it('with BUCKETTIMESTAMP', () => { // it('with BUCKETTIMESTAMP', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
AGGREGATION: { // AGGREGATION: {
type: TimeSeriesAggregationType.FIRST, // type: TimeSeriesAggregationType.FIRST,
timeBucket: 1, // timeBucket: 1,
BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW // BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW
} // }
}), // }),
['-', '+', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-'] // ['-', '+', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-']
); // );
}); // });
it('with BUCKETTIMESTAMP', () => { // it('with BUCKETTIMESTAMP', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
AGGREGATION: { // AGGREGATION: {
type: TimeSeriesAggregationType.FIRST, // type: TimeSeriesAggregationType.FIRST,
timeBucket: 1, // timeBucket: 1,
EMPTY: true // EMPTY: true
} // }
}), // }),
['-', '+', 'AGGREGATION', 'FIRST', '1', 'EMPTY'] // ['-', '+', 'AGGREGATION', 'FIRST', '1', 'EMPTY']
); // );
}); // });
}); // });
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => { // it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
assert.deepEqual( // assert.deepEqual(
pushRangeArguments([], '-', '+', { // pushRangeArguments([], '-', '+', {
FILTER_BY_TS: ['ts'], // FILTER_BY_TS: ['ts'],
FILTER_BY_VALUE: { // FILTER_BY_VALUE: {
min: 1, // min: 1,
max: 2 // max: 2
}, // },
COUNT: 1, // COUNT: 1,
ALIGN: 1, // ALIGN: 1,
AGGREGATION: { // AGGREGATION: {
type: TimeSeriesAggregationType.FIRST, // type: TimeSeriesAggregationType.FIRST,
timeBucket: 1, // timeBucket: 1,
BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW, // BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW,
EMPTY: true // EMPTY: true
} // }
}), // }),
['-', '+', 'FILTER_BY_TS', 'ts', 'FILTER_BY_VALUE', '1', '2', // ['-', '+', 'FILTER_BY_TS', 'ts', 'FILTER_BY_VALUE', '1', '2',
'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-', 'EMPTY'] // 'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-', 'EMPTY']
); // );
}); // });
}); // });
describe('pushMRangeGroupByArguments', () => { // describe('pushMRangeGroupByArguments', () => {
it('undefined', () => { // it('undefined', () => {
assert.deepEqual( // assert.deepEqual(
pushMRangeGroupByArguments([]), // pushMRangeGroupByArguments([]),
[] // []
); // );
}); // });
it('with GROUPBY', () => { // it('with GROUPBY', () => {
assert.deepEqual( // assert.deepEqual(
pushMRangeGroupByArguments([], { // pushMRangeGroupByArguments([], {
label: 'label', // label: 'label',
reducer: TimeSeriesReducers.MAXIMUM // reducer: TimeSeriesReducers.MAXIMUM
}), // }),
['GROUPBY', 'label', 'REDUCE', 'MAX'] // ['GROUPBY', 'label', 'REDUCE', 'MAX']
); // );
}); // });
}); // });
describe('pushFilterArgument', () => { // describe('pushFilterArgument', () => {
it('string', () => { // it('string', () => {
assert.deepEqual( // assert.deepEqual(
pushFilterArgument([], 'label=value'), // pushFilterArgument([], 'label=value'),
['FILTER', 'label=value'] // ['FILTER', 'label=value']
); // );
}); // });
it('Array', () => { // it('Array', () => {
assert.deepEqual( // assert.deepEqual(
pushFilterArgument([], ['1=1', '2=2']), // pushFilterArgument([], ['1=1', '2=2']),
['FILTER', '1=1', '2=2'] // ['FILTER', '1=1', '2=2']
); // );
}); // });
}); // });
describe('pushMRangeArguments', () => { // describe('pushMRangeArguments', () => {
it('without options', () => { // it('without options', () => {
assert.deepEqual( // assert.deepEqual(
pushMRangeArguments([], '-', '+', 'label=value'), // pushMRangeArguments([], '-', '+', 'label=value'),
['-', '+', 'FILTER', 'label=value'] // ['-', '+', 'FILTER', 'label=value']
); // );
}); // });
it('with GROUPBY', () => { // it('with GROUPBY', () => {
assert.deepEqual( // assert.deepEqual(
pushMRangeArguments([], '-', '+', 'label=value', { // pushMRangeArguments([], '-', '+', 'label=value', {
GROUPBY: { // GROUPBY: {
label: 'label', // label: 'label',
reducer: TimeSeriesReducers.MAXIMUM // reducer: TimeSeriesReducers.MAXIMUM
} // }
}), // }),
['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'MAX'] // ['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'MAX']
); // );
}); // });
}); // });
describe('pushWithLabelsArgument', () => { // describe('pushWithLabelsArgument', () => {
it('without selected labels', () => { // it('without selected labels', () => {
assert.deepEqual( // assert.deepEqual(
pushWithLabelsArgument([]), // pushWithLabelsArgument([]),
['WITHLABELS'] // ['WITHLABELS']
); // );
}); // });
it('with selected labels', () => { // it('with selected labels', () => {
assert.deepEqual( // assert.deepEqual(
pushWithLabelsArgument([], ['label']), // pushWithLabelsArgument([], ['label']),
['SELECTED_LABELS', 'label'] // ['SELECTED_LABELS', 'label']
); // );
}); // });
}); // });
it('pushMRangeWithLabelsArguments', () => { // it('pushMRangeWithLabelsArguments', () => {
assert.deepEqual( // assert.deepEqual(
pushMRangeWithLabelsArguments([], '-', '+', 'label=value'), // pushMRangeWithLabelsArguments([], '-', '+', 'label=value'),
['-', '+', 'WITHLABELS', 'FILTER', 'label=value'] // ['-', '+', 'WITHLABELS', 'FILTER', 'label=value']
); // );
}); // });
it('transformRangeReply', () => { // it('transformRangeReply', () => {
assert.deepEqual( // assert.deepEqual(
transformRangeReply([[1, '1.1'], [2, '2.2']]), // transformRangeReply([[1, '1.1'], [2, '2.2']]),
[{ // [{
timestamp: 1, // timestamp: 1,
value: 1.1 // value: 1.1
}, { // }, {
timestamp: 2, // timestamp: 2,
value: 2.2 // value: 2.2
}] // }]
); // );
}); // });
describe('transformMRangeReply', () => { // describe('transformMRangeReply', () => {
assert.deepEqual( // assert.deepEqual(
transformMRangeReply([[ // transformMRangeReply([[
'key', // 'key',
[], // [],
[[1, '1.1'], [2, '2.2']] // [[1, '1.1'], [2, '2.2']]
]]), // ]]),
[{ // [{
key: 'key', // key: 'key',
samples: [{ // samples: [{
timestamp: 1, // timestamp: 1,
value: 1.1 // value: 1.1
}, { // }, {
timestamp: 2, // timestamp: 2,
value: 2.2 // value: 2.2
}] // }]
}] // }]
); // );
}); // });
describe('transformMRangeWithLabelsReply', () => { // describe('transformMRangeWithLabelsReply', () => {
assert.deepEqual( // assert.deepEqual(
transformMRangeWithLabelsReply([[ // transformMRangeWithLabelsReply([[
'key', // 'key',
[['label', 'value']], // [['label', 'value']],
[[1, '1.1'], [2, '2.2']] // [[1, '1.1'], [2, '2.2']]
]]), // ]]),
[{ // [{
key: 'key', // key: 'key',
labels: { // labels: {
label: 'value' // label: 'value'
}, // },
samples: [{ // samples: [{
timestamp: 1, // timestamp: 1,
value: 1.1 // value: 1.1
}, { // }, {
timestamp: 2, // timestamp: 2,
value: 2.2 // value: 2.2
}] // }]
}] // }]
); // );
}); // });
describe('pushLatestArgument', () => { // describe('pushLatestArgument', () => {
it('undefined', () => { // it('undefined', () => {
assert.deepEqual( // assert.deepEqual(
pushLatestArgument([]), // pushLatestArgument([]),
[] // []
); // );
}); // });
it('false', () => { // it('false', () => {
assert.deepEqual( // assert.deepEqual(
pushLatestArgument([], false), // pushLatestArgument([], false),
[] // []
); // );
}); // });
it('true', () => { // it('true', () => {
assert.deepEqual( // assert.deepEqual(
pushLatestArgument([], true), // pushLatestArgument([], true),
['LATEST'] // ['LATEST']
); // );
}); // });
}) // })

View File

@@ -1,467 +1,367 @@
import * as ADD from './ADD'; import type { RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types';
import * as ALTER from './ALTER'; import ADD from './ADD';
import * as CREATE from './CREATE'; import ALTER from './ALTER';
import * as CREATERULE from './CREATERULE'; import CREATE from './CREATE';
import * as DECRBY from './DECRBY'; import CREATERULE from './CREATERULE';
import * as DEL from './DEL'; import DECRBY from './DECRBY';
import * as DELETERULE from './DELETERULE'; import DEL from './DEL';
import * as GET from './GET'; import DELETERULE from './DELETERULE';
import * as INCRBY from './INCRBY'; import GET from './GET';
import * as INFO_DEBUG from './INFO_DEBUG'; import INCRBY from './INCRBY';
import * as INFO from './INFO'; // import INFO_DEBUG from './INFO_DEBUG';
import * as MADD from './MADD'; // import INFO from './INFO';
import * as MGET from './MGET'; import MADD from './MADD';
import * as MGET_WITHLABELS from './MGET_WITHLABELS'; // import MGET from './MGET';
import * as QUERYINDEX from './QUERYINDEX'; // import MGET_WITHLABELS from './MGET_WITHLABELS';
import * as RANGE from './RANGE'; // import QUERYINDEX from './QUERYINDEX';
import * as REVRANGE from './REVRANGE'; // import RANGE from './RANGE';
import * as MRANGE from './MRANGE'; // import REVRANGE from './REVRANGE';
import * as MRANGE_WITHLABELS from './MRANGE_WITHLABELS'; // import MRANGE from './MRANGE';
import * as MREVRANGE from './MREVRANGE'; // import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
import * as MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS'; // import MREVRANGE from './MREVRANGE';
import { RedisCommandArguments } from '@redis/client/dist/lib/commands'; // import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
export default { export default {
ADD, ADD,
add: ADD, add: ADD,
ALTER, ALTER,
alter: ALTER, alter: ALTER,
CREATE, CREATE,
create: CREATE, create: CREATE,
CREATERULE, CREATERULE,
createRule: CREATERULE, createRule: CREATERULE,
DECRBY, DECRBY,
decrBy: DECRBY, decrBy: DECRBY,
DEL, DEL,
del: DEL, del: DEL,
DELETERULE, DELETERULE,
deleteRule: DELETERULE, deleteRule: DELETERULE,
GET, GET,
get: GET, get: GET,
INCRBY, INCRBY,
incrBy: INCRBY, incrBy: INCRBY,
INFO_DEBUG, // INFO_DEBUG,
infoDebug: INFO_DEBUG, // infoDebug: INFO_DEBUG,
INFO, // INFO,
info: INFO, // info: INFO,
MADD, MADD,
mAdd: MADD, mAdd: MADD,
MGET, // MGET,
mGet: MGET, // mGet: MGET,
MGET_WITHLABELS, // MGET_WITHLABELS,
mGetWithLabels: MGET_WITHLABELS, // mGetWithLabels: MGET_WITHLABELS,
QUERYINDEX, // QUERYINDEX,
queryIndex: QUERYINDEX, // queryIndex: QUERYINDEX,
RANGE, // RANGE,
range: RANGE, // range: RANGE,
REVRANGE, // REVRANGE,
revRange: REVRANGE, // revRange: REVRANGE,
MRANGE, // MRANGE,
mRange: MRANGE, // mRange: MRANGE,
MRANGE_WITHLABELS, // MRANGE_WITHLABELS,
mRangeWithLabels: MRANGE_WITHLABELS, // mRangeWithLabels: MRANGE_WITHLABELS,
MREVRANGE, // MREVRANGE,
mRevRange: MREVRANGE, // mRevRange: MREVRANGE,
MREVRANGE_WITHLABELS, // MREVRANGE_WITHLABELS,
mRevRangeWithLabels: MREVRANGE_WITHLABELS // mRevRangeWithLabels: MREVRANGE_WITHLABELS
}; } as const satisfies RedisCommands;
export enum TimeSeriesAggregationType { export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
AVG = 'AVG', if (retention !== undefined) {
// @deprecated args.push('RETENTION', retention.toString());
AVERAGE = 'AVG', }
FIRST = 'FIRST',
LAST = 'LAST',
MIN = 'MIN',
// @deprecated
MINIMUM = 'MIN',
MAX = 'MAX',
// @deprecated
MAXIMUM = 'MAX',
SUM = 'SUM',
RANGE = 'RANGE',
COUNT = 'COUNT',
STD_P = 'STD.P',
STD_S = 'STD.S',
VAR_P = 'VAR.P',
VAR_S = 'VAR.S',
TWA = 'TWA'
} }
export enum TimeSeriesDuplicatePolicies { export const TIME_SERIES_ENCODING = {
BLOCK = 'BLOCK', COMPRESSED: 'COMPRESSED',
FIRST = 'FIRST', UNCOMPRESSED: 'UNCOMPRESSED'
LAST = 'LAST', } as const;
MIN = 'MIN',
MAX = 'MAX', export type TimeSeriesEncoding = typeof TIME_SERIES_ENCODING[keyof typeof TIME_SERIES_ENCODING];
SUM = 'SUM'
export function pushEncodingArgument(args: Array<RedisArgument>, encoding?: TimeSeriesEncoding) {
if (encoding !== undefined) {
args.push('ENCODING', encoding);
}
} }
export enum TimeSeriesReducers { export function pushChunkSizeArgument(args: Array<RedisArgument>, chunkSize?: number) {
AVG = 'AVG', if (chunkSize !== undefined) {
SUM = 'SUM', args.push('CHUNK_SIZE', chunkSize.toString());
MIN = 'MIN', }
// @deprecated }
MINIMUM = 'MIN',
MAX = 'MAX', export const TIME_SERIES_DUPLICATE_POLICIES = {
// @deprecated BLOCK: 'BLOCK',
MAXIMUM = 'MAX', FIRST: 'FIRST',
RANGE = 'range', LAST: 'LAST',
COUNT = 'COUNT', MIN: 'MIN',
STD_P = 'STD.P', MAX: 'MAX',
STD_S = 'STD.S', SUM: 'SUM'
VAR_P = 'VAR.P', } as const;
VAR_S = 'VAR.S',
export type TimeSeriesDuplicatePolicies = typeof TIME_SERIES_DUPLICATE_POLICIES[keyof typeof TIME_SERIES_DUPLICATE_POLICIES];
export function pushDuplicatePolicy(args: Array<RedisArgument>, duplicatePolicy?: TimeSeriesDuplicatePolicies) {
if (duplicatePolicy !== undefined) {
args.push('DUPLICATE_POLICY', duplicatePolicy);
}
} }
export type Timestamp = number | Date | string; export type Timestamp = number | Date | string;
export function transformTimestampArgument(timestamp: Timestamp): string { export function transformTimestampArgument(timestamp: Timestamp): string {
if (typeof timestamp === 'string') return timestamp; if (typeof timestamp === 'string') return timestamp;
return ( return (
typeof timestamp === 'number' ? typeof timestamp === 'number' ?
timestamp : timestamp :
timestamp.getTime() timestamp.getTime()
).toString(); ).toString();
} }
export function pushRetentionArgument(args: RedisCommandArguments, retention?: number): RedisCommandArguments {
if (retention !== undefined) {
args.push(
'RETENTION',
retention.toString()
);
}
return args;
}
export enum TimeSeriesEncoding {
COMPRESSED = 'COMPRESSED',
UNCOMPRESSED = 'UNCOMPRESSED'
}
export function pushEncodingArgument(args: RedisCommandArguments, encoding?: TimeSeriesEncoding): RedisCommandArguments {
if (encoding !== undefined) {
args.push(
'ENCODING',
encoding
);
}
return args;
}
export function pushChunkSizeArgument(args: RedisCommandArguments, chunkSize?: number): RedisCommandArguments {
if (chunkSize !== undefined) {
args.push(
'CHUNK_SIZE',
chunkSize.toString()
);
}
return args;
}
export function pushDuplicatePolicy(args: RedisCommandArguments, duplicatePolicy?: TimeSeriesDuplicatePolicies): RedisCommandArguments {
if (duplicatePolicy !== undefined) {
args.push(
'DUPLICATE_POLICY',
duplicatePolicy
);
}
return args;
}
export type RawLabels = Array<[label: string, value: string]>;
export type Labels = { export type Labels = {
[label: string]: string; [label: string]: string;
}; };
export function transformLablesReply(reply: RawLabels): Labels { export function pushLabelsArgument(args: Array<RedisArgument>, labels?: Labels) {
const labels: Labels = {}; if (labels) {
args.push('LABELS');
for (const [key, value] of reply) { for (const [label, value] of Object.entries(labels)) {
labels[key] = value; args.push(label, value);
} }
}
return labels return args;
} }
export function pushLabelsArgument(args: RedisCommandArguments, labels?: Labels): RedisCommandArguments { // export type RawLabelsReply = ArrayReply<TuplesReply<[BlobStringReply, BlobStringReply]>>;
if (labels) {
args.push('LABELS');
for (const [label, value] of Object.entries(labels)) { // export function transformLablesReply(reply: RawLabelsReply) {
args.push(label, value); // const labels: Record<string, BlobStringReply> = {};
}
}
return args; // for (const [key, value] of reply) {
} // labels[key.toString()] = value;
// }
export interface IncrDecrOptions { // return labels
TIMESTAMP?: Timestamp; // }
RETENTION?: number;
UNCOMPRESSED?: boolean;
CHUNK_SIZE?: number;
LABELS?: Labels;
}
export function transformIncrDecrArguments(
command: 'TS.INCRBY' | 'TS.DECRBY',
key: string,
value: number,
options?: IncrDecrOptions
): RedisCommandArguments {
const args = [
command,
key,
value.toString()
];
if (options?.TIMESTAMP !== undefined && options?.TIMESTAMP !== null) { // export type SampleRawReply = [timestamp: number, value: string];
args.push('TIMESTAMP', transformTimestampArgument(options.TIMESTAMP));
}
pushRetentionArgument(args, options?.RETENTION); // export interface SampleReply {
// timestamp: number;
// value: number;
// }
if (options?.UNCOMPRESSED) { // export function transformSampleReply(reply: SampleRawReply): SampleReply {
args.push('UNCOMPRESSED'); // return {
} // timestamp: reply[0],
// value: Number(reply[1])
// };
// }
pushChunkSizeArgument(args, options?.CHUNK_SIZE); // export enum TimeSeriesBucketTimestamp {
// LOW = '-',
// HIGH = '+',
// MID = '~'
// }
pushLabelsArgument(args, options?.LABELS); // export interface RangeOptions {
// LATEST?: boolean;
// FILTER_BY_TS?: Array<Timestamp>;
// FILTER_BY_VALUE?: {
// min: number;
// max: number;
// };
// COUNT?: number;
// ALIGN?: Timestamp;
// AGGREGATION?: {
// type: TimeSeriesAggregationType;
// timeBucket: Timestamp;
// BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp;
// EMPTY?: boolean;
// };
// }
return args; // export function pushRangeArguments(
} // args: RedisCommandArguments,
// fromTimestamp: Timestamp,
// toTimestamp: Timestamp,
// options?: RangeOptions
// ): RedisCommandArguments {
// args.push(
// transformTimestampArgument(fromTimestamp),
// transformTimestampArgument(toTimestamp)
// );
export type SampleRawReply = [timestamp: number, value: string]; // pushLatestArgument(args, options?.LATEST);
export interface SampleReply { // if (options?.FILTER_BY_TS) {
timestamp: number; // args.push('FILTER_BY_TS');
value: number; // for (const ts of options.FILTER_BY_TS) {
} // args.push(transformTimestampArgument(ts));
// }
// }
export function transformSampleReply(reply: SampleRawReply): SampleReply { // if (options?.FILTER_BY_VALUE) {
return { // args.push(
timestamp: reply[0], // 'FILTER_BY_VALUE',
value: Number(reply[1]) // options.FILTER_BY_VALUE.min.toString(),
}; // options.FILTER_BY_VALUE.max.toString()
} // );
// }
export enum TimeSeriesBucketTimestamp { // if (options?.COUNT) {
LOW = '-', // args.push(
HIGH = '+', // 'COUNT',
MID = '~' // options.COUNT.toString()
} // );
// }
export interface RangeOptions { // if (options?.ALIGN) {
LATEST?: boolean; // args.push(
FILTER_BY_TS?: Array<Timestamp>; // 'ALIGN',
FILTER_BY_VALUE?: { // transformTimestampArgument(options.ALIGN)
min: number; // );
max: number; // }
};
COUNT?: number;
ALIGN?: Timestamp;
AGGREGATION?: {
type: TimeSeriesAggregationType;
timeBucket: Timestamp;
BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp;
EMPTY?: boolean;
};
}
export function pushRangeArguments( // if (options?.AGGREGATION) {
args: RedisCommandArguments, // args.push(
fromTimestamp: Timestamp, // 'AGGREGATION',
toTimestamp: Timestamp, // options.AGGREGATION.type,
options?: RangeOptions // transformTimestampArgument(options.AGGREGATION.timeBucket)
): RedisCommandArguments { // );
args.push(
transformTimestampArgument(fromTimestamp),
transformTimestampArgument(toTimestamp)
);
pushLatestArgument(args, options?.LATEST); // if (options.AGGREGATION.BUCKETTIMESTAMP) {
// args.push(
// 'BUCKETTIMESTAMP',
// options.AGGREGATION.BUCKETTIMESTAMP
// );
// }
if (options?.FILTER_BY_TS) { // if (options.AGGREGATION.EMPTY) {
args.push('FILTER_BY_TS'); // args.push('EMPTY');
for (const ts of options.FILTER_BY_TS) { // }
args.push(transformTimestampArgument(ts)); // }
}
}
if (options?.FILTER_BY_VALUE) { // return args;
args.push( // }
'FILTER_BY_VALUE',
options.FILTER_BY_VALUE.min.toString(),
options.FILTER_BY_VALUE.max.toString()
);
}
if (options?.COUNT) { // interface MRangeGroupBy {
args.push( // label: string;
'COUNT', // reducer: TimeSeriesReducers;
options.COUNT.toString() // }
);
}
if (options?.ALIGN) { // export function pushMRangeGroupByArguments(args: RedisCommandArguments, groupBy?: MRangeGroupBy): RedisCommandArguments {
args.push( // if (groupBy) {
'ALIGN', // args.push(
transformTimestampArgument(options.ALIGN) // 'GROUPBY',
); // groupBy.label,
} // 'REDUCE',
// groupBy.reducer
// );
// }
if (options?.AGGREGATION) { // return args;
args.push( // }
'AGGREGATION',
options.AGGREGATION.type,
transformTimestampArgument(options.AGGREGATION.timeBucket)
);
if (options.AGGREGATION.BUCKETTIMESTAMP) { // export type Filter = string | Array<string>;
args.push(
'BUCKETTIMESTAMP',
options.AGGREGATION.BUCKETTIMESTAMP
);
}
if (options.AGGREGATION.EMPTY) { // export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array<string>): RedisCommandArguments {
args.push('EMPTY'); // args.push('FILTER');
} // return pushVariadicArguments(args, filter);
} // }
return args; // export interface MRangeOptions extends RangeOptions {
} // GROUPBY?: MRangeGroupBy;
// }
interface MRangeGroupBy { // export function pushMRangeArguments(
label: string; // args: RedisCommandArguments,
reducer: TimeSeriesReducers; // fromTimestamp: Timestamp,
} // toTimestamp: Timestamp,
// filter: Filter,
// options?: MRangeOptions
// ): RedisCommandArguments {
// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options);
// args = pushFilterArgument(args, filter);
// return pushMRangeGroupByArguments(args, options?.GROUPBY);
// }
export function pushMRangeGroupByArguments(args: RedisCommandArguments, groupBy?: MRangeGroupBy): RedisCommandArguments { // export type SelectedLabels = string | Array<string>;
if (groupBy) {
args.push(
'GROUPBY',
groupBy.label,
'REDUCE',
groupBy.reducer
);
}
return args; // export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments {
} // if (!selectedLabels) {
// args.push('WITHLABELS');
// } else {
// args.push('SELECTED_LABELS');
// args = pushVariadicArguments(args, selectedLabels);
// }
export type Filter = string | Array<string>; // return args;
// }
export function pushFilterArgument(args: RedisCommandArguments, filter: string | Array<string>): RedisCommandArguments { // export interface MRangeWithLabelsOptions extends MRangeOptions {
args.push('FILTER'); // SELECTED_LABELS?: SelectedLabels;
return pushVariadicArguments(args, filter); // }
}
export interface MRangeOptions extends RangeOptions { // export function pushMRangeWithLabelsArguments(
GROUPBY?: MRangeGroupBy; // args: RedisCommandArguments,
} // fromTimestamp: Timestamp,
// toTimestamp: Timestamp,
// filter: Filter,
// options?: MRangeWithLabelsOptions
// ): RedisCommandArguments {
// args = pushRangeArguments(args, fromTimestamp, toTimestamp, options);
// args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
// args = pushFilterArgument(args, filter);
// return pushMRangeGroupByArguments(args, options?.GROUPBY);
// }
export function pushMRangeArguments( // export function transformRangeReply(reply: Array<SampleRawReply>): Array<SampleReply> {
args: RedisCommandArguments, // return reply.map(transformSampleReply);
fromTimestamp: Timestamp, // }
toTimestamp: Timestamp,
filter: Filter,
options?: MRangeOptions
): RedisCommandArguments {
args = pushRangeArguments(args, fromTimestamp, toTimestamp, options);
args = pushFilterArgument(args, filter);
return pushMRangeGroupByArguments(args, options?.GROUPBY);
}
export type SelectedLabels = string | Array<string>; // type MRangeRawReply = Array<[
// key: string,
// labels: RawLabels,
// samples: Array<SampleRawReply>
// ]>;
export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments { // interface MRangeReplyItem {
if (!selectedLabels) { // key: string;
args.push('WITHLABELS'); // samples: Array<SampleReply>;
} else { // }
args.push('SELECTED_LABELS');
args = pushVariadicArguments(args, selectedLabels);
}
return args; // export function transformMRangeReply(reply: MRangeRawReply): Array<MRangeReplyItem> {
} // const args = [];
export interface MRangeWithLabelsOptions extends MRangeOptions { // for (const [key, _, sample] of reply) {
SELECTED_LABELS?: SelectedLabels; // args.push({
} // key,
// samples: sample.map(transformSampleReply)
// });
// }
export function pushMRangeWithLabelsArguments( // return args;
args: RedisCommandArguments, // }
fromTimestamp: Timestamp, // export interface MRangeWithLabelsReplyItem extends MRangeReplyItem {
toTimestamp: Timestamp, // labels: Labels;
filter: Filter, // }
options?: MRangeWithLabelsOptions
): RedisCommandArguments {
args = pushRangeArguments(args, fromTimestamp, toTimestamp, options);
args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
args = pushFilterArgument(args, filter);
return pushMRangeGroupByArguments(args, options?.GROUPBY);
}
export function transformRangeReply(reply: Array<SampleRawReply>): Array<SampleReply> { // export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array<MRangeWithLabelsReplyItem> {
return reply.map(transformSampleReply); // const args = [];
}
type MRangeRawReply = Array<[ // for (const [key, labels, samples] of reply) {
key: string, // args.push({
labels: RawLabels, // key,
samples: Array<SampleRawReply> // labels: transformLablesReply(labels),
]>; // samples: samples.map(transformSampleReply)
// });
// }
interface MRangeReplyItem { // return args;
key: string; // }
samples: Array<SampleReply>;
}
export function transformMRangeReply(reply: MRangeRawReply): Array<MRangeReplyItem> {
const args = [];
for (const [key, _, sample] of reply) {
args.push({
key,
samples: sample.map(transformSampleReply)
});
}
return args;
}
export interface MRangeWithLabelsReplyItem extends MRangeReplyItem {
labels: Labels;
}
export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array<MRangeWithLabelsReplyItem> {
const args = [];
for (const [key, labels, samples] of reply) {
args.push({
key,
labels: transformLablesReply(labels),
samples: samples.map(transformSampleReply)
});
}
return args;
}
export function pushLatestArgument(args: RedisCommandArguments, latest?: boolean): RedisCommandArguments {
if (latest) {
args.push('LATEST');
}
return args;
}

View File

@@ -1,9 +1,11 @@
export { default } from './commands'; export { default } from './commands';
export { export {
TimeSeriesDuplicatePolicies, TIME_SERIES_ENCODING,
TimeSeriesEncoding, TimeSeriesEncoding,
TimeSeriesAggregationType, TIME_SERIES_DUPLICATE_POLICIES,
TimeSeriesReducers, TimeSeriesDuplicatePolicies,
TimeSeriesBucketTimestamp // TimeSeriesBucketTimestamp
} from './commands'; } from './commands';
export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE';

View File

@@ -2,19 +2,19 @@ import TestUtils from '@redis/test-utils';
import TimeSeries from '.'; import TimeSeries from '.';
export default new TestUtils({ export default new TestUtils({
dockerImageName: 'redislabs/redistimeseries', dockerImageName: 'redislabs/redistimeseries',
dockerImageVersionArgument: 'timeseries-version' dockerImageVersionArgument: 'timeseries-version'
}); });
export const GLOBAL = { export const GLOBAL = {
SERVERS: { SERVERS: {
OPEN: { OPEN: {
serverArguments: ['--loadmodule /usr/lib/redis/modules/redistimeseries.so'], serverArguments: ['--loadmodule /usr/lib/redis/modules/redistimeseries.so'],
clientOptions: { clientOptions: {
modules: { modules: {
ts: TimeSeries ts: TimeSeries
}
}
} }
}
} }
}
}; };