You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-04 15:02:09 +03:00
close #2192 close #2193 close #2194 close #2195 close #2196 close #2197 close #2198 - support for TimeSeries 1.8 (#2200)
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TimeSeriesDuplicatePolicies } from '.';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './ALTER';
|
||||
|
||||
@@ -20,6 +21,24 @@ describe('ALTER', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('with CHUNK_SIZE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
CHUNK_SIZE: 1
|
||||
}),
|
||||
['TS.ALTER', 'key', 'CHUNK_SIZE', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with DUPLICATE_POLICY', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK
|
||||
}),
|
||||
['TS.ALTER', 'key', 'DUPLICATE_POLICY', 'BLOCK']
|
||||
);
|
||||
});
|
||||
|
||||
it('with LABELS', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
@@ -29,19 +48,21 @@ describe('ALTER', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('with RETENTION, LABELS', () => {
|
||||
it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
RETENTION: 1,
|
||||
CHUNK_SIZE: 1,
|
||||
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK,
|
||||
LABELS: { label: 'value' }
|
||||
}),
|
||||
['TS.ALTER', 'key', 'RETENTION', '1', 'LABELS', 'label', 'value']
|
||||
['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.alter', async client => {
|
||||
await client.ts.create('key');
|
||||
await client.ts.create('key');
|
||||
|
||||
assert.equal(
|
||||
await client.ts.alter('key', { RETENTION: 1 }),
|
||||
|
@@ -1,9 +1,11 @@
|
||||
import { pushRetentionArgument, Labels, pushLabelsArgument } from '.';
|
||||
import { pushRetentionArgument, Labels, pushLabelsArgument, TimeSeriesDuplicatePolicies, pushChunkSizeArgument, pushDuplicatePolicy } from '.';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
interface AlterOptions {
|
||||
RETENTION?: number;
|
||||
CHUNK_SIZE?: number;
|
||||
DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies;
|
||||
LABELS?: Labels;
|
||||
}
|
||||
|
||||
@@ -12,6 +14,10 @@ export function transformArguments(key: string, options?: AlterOptions): Array<s
|
||||
|
||||
pushRetentionArgument(args, options?.RETENTION);
|
||||
|
||||
pushChunkSizeArgument(args, options?.CHUNK_SIZE);
|
||||
|
||||
pushDuplicatePolicy(args, options?.DUPLICATE_POLICY);
|
||||
|
||||
pushLabelsArgument(args, options?.LABELS);
|
||||
|
||||
return args;
|
||||
|
@@ -5,7 +5,8 @@ import {
|
||||
pushChunkSizeArgument,
|
||||
TimeSeriesDuplicatePolicies,
|
||||
Labels,
|
||||
pushLabelsArgument
|
||||
pushLabelsArgument,
|
||||
pushDuplicatePolicy
|
||||
} from '.';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
@@ -27,12 +28,7 @@ export function transformArguments(key: string, options?: CreateOptions): Array<
|
||||
|
||||
pushChunkSizeArgument(args, options?.CHUNK_SIZE);
|
||||
|
||||
if (options?.DUPLICATE_POLICY) {
|
||||
args.push(
|
||||
'DUPLICATE_POLICY',
|
||||
options.DUPLICATE_POLICY
|
||||
);
|
||||
}
|
||||
pushDuplicatePolicy(args, options?.DUPLICATE_POLICY);
|
||||
|
||||
pushLabelsArgument(args, options?.LABELS);
|
||||
|
||||
|
@@ -4,11 +4,20 @@ import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './CREATERULE';
|
||||
|
||||
describe('CREATERULE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1),
|
||||
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'avg', '1']
|
||||
);
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1),
|
||||
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with alignTimestamp', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1, 1),
|
||||
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'AVG', '1', '1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.createRule', async client => {
|
||||
|
@@ -6,16 +6,23 @@ export function transformArguments(
|
||||
sourceKey: string,
|
||||
destinationKey: string,
|
||||
aggregationType: TimeSeriesAggregationType,
|
||||
timeBucket: number
|
||||
bucketDuration: number,
|
||||
alignTimestamp?: number
|
||||
): Array<string> {
|
||||
return [
|
||||
const args = [
|
||||
'TS.CREATERULE',
|
||||
sourceKey,
|
||||
destinationKey,
|
||||
'AGGREGATION',
|
||||
aggregationType,
|
||||
timeBucket.toString()
|
||||
bucketDuration.toString()
|
||||
];
|
||||
|
||||
if (alignTimestamp) {
|
||||
args.push(alignTimestamp.toString());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export declare function transformReply(): 'OK';
|
||||
|
@@ -4,7 +4,7 @@ export function transformArguments(sourceKey: string, destinationKey: string): A
|
||||
return [
|
||||
'TS.DELETERULE',
|
||||
sourceKey,
|
||||
destinationKey,
|
||||
destinationKey
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -3,11 +3,22 @@ import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './GET';
|
||||
|
||||
describe('GET', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['TS.GET', 'key']
|
||||
);
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key'),
|
||||
['TS.GET', 'key']
|
||||
);
|
||||
});
|
||||
|
||||
it('with LATEST', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', {
|
||||
LATEST: true
|
||||
}),
|
||||
['TS.GET', 'key', 'LATEST']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('client.ts.get', () => {
|
||||
|
@@ -1,11 +1,16 @@
|
||||
import { SampleRawReply, SampleReply, transformSampleReply } from '.';
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { pushLatestArgument, SampleRawReply, SampleReply, transformSampleReply } from '.';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(key: string): Array<string> {
|
||||
return ['TS.GET', key];
|
||||
interface GetOptions {
|
||||
LATEST?: boolean;
|
||||
}
|
||||
|
||||
export function transformArguments(key: string, options?: GetOptions): RedisCommandArguments {
|
||||
return pushLatestArgument(['TS.GET', key], options?.LATEST);
|
||||
}
|
||||
|
||||
export function transformReply(reply: [] | SampleRawReply): null | SampleReply {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './INFO';
|
||||
import { InfoReply, transformArguments } from './INFO';
|
||||
|
||||
describe('INFO', () => {
|
||||
it('transformArguments', () => {
|
||||
@@ -14,7 +14,7 @@ describe('INFO', () => {
|
||||
testUtils.testWithClient('client.ts.info', async client => {
|
||||
await Promise.all([
|
||||
client.ts.create('key', {
|
||||
LABELS: { id: "2" },
|
||||
LABELS: { id: '1' },
|
||||
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.LAST
|
||||
}),
|
||||
client.ts.create('key2'),
|
||||
@@ -22,29 +22,32 @@ describe('INFO', () => {
|
||||
client.ts.add('key', 1, 10)
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.info('key'),
|
||||
{
|
||||
totalSamples: 1,
|
||||
memoryUsage: 4261,
|
||||
firstTimestamp: 1,
|
||||
lastTimestamp: 1,
|
||||
retentionTime: 0,
|
||||
chunkCount: 1,
|
||||
chunkSize: 4096,
|
||||
chunkType: 'compressed',
|
||||
duplicatePolicy: 'last',
|
||||
labels: [{
|
||||
name: 'id',
|
||||
value: '2'
|
||||
}],
|
||||
rules: [{
|
||||
aggregationType: 'COUNT',
|
||||
key: 'key2',
|
||||
timeBucket: 5
|
||||
}],
|
||||
sourceKey: null
|
||||
}
|
||||
);
|
||||
assertInfo(await client.ts.info('key'));
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
||||
export function assertInfo(info: InfoReply): void {
|
||||
assert.equal(typeof info.totalSamples, 'number');
|
||||
assert.equal(typeof info.memoryUsage, 'number');
|
||||
assert.equal(typeof info.firstTimestamp, 'number');
|
||||
assert.equal(typeof info.lastTimestamp, 'number');
|
||||
assert.equal(typeof info.retentionTime, 'number');
|
||||
assert.equal(typeof info.chunkCount, 'number');
|
||||
assert.equal(typeof info.chunkSize, 'number');
|
||||
assert.equal(typeof info.chunkType, 'string');
|
||||
assert.equal(typeof info.duplicatePolicy, 'string');
|
||||
assert.ok(Array.isArray(info.labels));
|
||||
for (const label of info.labels) {
|
||||
assert.equal(typeof label, 'object');
|
||||
assert.equal(typeof label.name, 'string');
|
||||
assert.equal(typeof label.value, 'string');
|
||||
}
|
||||
assert.ok(Array.isArray(info.rules));
|
||||
for (const rule of info.rules) {
|
||||
assert.equal(typeof rule, 'object');
|
||||
assert.equal(typeof rule.aggregationType, 'string');
|
||||
assert.equal(typeof rule.key, 'string');
|
||||
assert.equal(typeof rule.timeBucket, 'number');
|
||||
}
|
||||
assert.ok(info.sourceKey === null || typeof info.sourceKey === 'string');
|
||||
}
|
||||
|
@@ -9,30 +9,30 @@ export function transformArguments(key: string): Array<string> {
|
||||
}
|
||||
|
||||
export type InfoRawReply = [
|
||||
_: string,
|
||||
totalSamples: number,
|
||||
_: string,
|
||||
memoryUsage: number,
|
||||
_: string,
|
||||
firstTimestamp: number,
|
||||
_: string,
|
||||
lastTimestamp: number,
|
||||
_: string,
|
||||
retentionTime: number,
|
||||
_: string,
|
||||
chunkCount: number,
|
||||
_: string,
|
||||
chunkSize: number,
|
||||
_: string,
|
||||
chunkType: string,
|
||||
_: string,
|
||||
duplicatePolicy: TimeSeriesDuplicatePolicies | null,
|
||||
_: string,
|
||||
labels: Array<[name: string, value: string]>,
|
||||
_: string,
|
||||
sourceKey: string | null,
|
||||
_: string,
|
||||
rules: Array<[key: string, timeBucket: number, aggregationType: TimeSeriesAggregationType]>
|
||||
'totalSamples',
|
||||
number,
|
||||
'memoryUsage',
|
||||
number,
|
||||
'firstTimestamp',
|
||||
number,
|
||||
'lastTimestamp',
|
||||
number,
|
||||
'retentionTime',
|
||||
number,
|
||||
'chunkCount',
|
||||
number,
|
||||
'chunkSize',
|
||||
number,
|
||||
'chunkType',
|
||||
string,
|
||||
'duplicatePolicy',
|
||||
TimeSeriesDuplicatePolicies | null,
|
||||
'labels',
|
||||
Array<[name: string, value: string]>,
|
||||
'sourceKey',
|
||||
string | null,
|
||||
'rules',
|
||||
Array<[key: string, timeBucket: number, aggregationType: TimeSeriesAggregationType]>
|
||||
];
|
||||
|
||||
export interface InfoReply {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import { TimeSeriesAggregationType, TimeSeriesDuplicatePolicies } from '.';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { assertInfo } from './INFO.spec';
|
||||
import { transformArguments } from './INFO_DEBUG';
|
||||
|
||||
describe('INFO_DEBUG', () => {
|
||||
@@ -14,7 +15,7 @@ describe('INFO_DEBUG', () => {
|
||||
testUtils.testWithClient('client.ts.get', async client => {
|
||||
await Promise.all([
|
||||
client.ts.create('key', {
|
||||
LABELS: { id: "2" },
|
||||
LABELS: { id: '1' },
|
||||
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.LAST
|
||||
}),
|
||||
client.ts.create('key2'),
|
||||
@@ -22,37 +23,17 @@ describe('INFO_DEBUG', () => {
|
||||
client.ts.add('key', 1, 10)
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.infoDebug('key'),
|
||||
{
|
||||
totalSamples: 1,
|
||||
memoryUsage: 4261,
|
||||
firstTimestamp: 1,
|
||||
lastTimestamp: 1,
|
||||
retentionTime: 0,
|
||||
chunkCount: 1,
|
||||
chunkSize: 4096,
|
||||
chunkType: 'compressed',
|
||||
duplicatePolicy: 'last',
|
||||
labels: [{
|
||||
name: 'id',
|
||||
value: '2'
|
||||
}],
|
||||
sourceKey: null,
|
||||
rules: [{
|
||||
aggregationType: 'COUNT',
|
||||
key: 'key2',
|
||||
timeBucket: 5
|
||||
}],
|
||||
keySelfName: 'key',
|
||||
chunks: [{
|
||||
startTimestamp: 1,
|
||||
endTimestamp: 1,
|
||||
samples: 1,
|
||||
size: 4096,
|
||||
bytesPerSample: '4096'
|
||||
}]
|
||||
}
|
||||
);
|
||||
const infoDebug = await client.ts.infoDebug('key');
|
||||
assertInfo(infoDebug);
|
||||
assert.equal(typeof infoDebug.keySelfName, 'string');
|
||||
assert.ok(Array.isArray(infoDebug.chunks));
|
||||
for (const chunk of infoDebug.chunks) {
|
||||
assert.equal(typeof chunk, 'object');
|
||||
assert.equal(typeof chunk.startTimestamp, 'number');
|
||||
assert.equal(typeof chunk.endTimestamp, 'number');
|
||||
assert.equal(typeof chunk.samples, 'number');
|
||||
assert.equal(typeof chunk.size, 'number');
|
||||
assert.equal(typeof chunk.bytesPerSample, 'string');
|
||||
}
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -14,23 +14,23 @@ export function transformArguments(key: string): Array<string> {
|
||||
}
|
||||
|
||||
type InfoDebugRawReply = [
|
||||
...infoArgs: InfoRawReply,
|
||||
_: string,
|
||||
keySelfName: string,
|
||||
_: string,
|
||||
chunks: Array<[
|
||||
_: string,
|
||||
startTimestamp: number,
|
||||
_: string,
|
||||
endTimestamp: number,
|
||||
_: string,
|
||||
samples: number,
|
||||
_: string,
|
||||
size: number,
|
||||
_: string,
|
||||
bytesPerSample: string
|
||||
...InfoRawReply,
|
||||
'keySelfName',
|
||||
string,
|
||||
'chunks',
|
||||
Array<[
|
||||
'startTimestamp',
|
||||
number,
|
||||
'endTimestamp',
|
||||
number,
|
||||
'samples',
|
||||
number,
|
||||
'size',
|
||||
number,
|
||||
'bytesPerSample',
|
||||
string
|
||||
]>
|
||||
]
|
||||
];
|
||||
|
||||
interface InfoDebugReply extends InfoReply {
|
||||
keySelfName: string;
|
||||
|
@@ -3,11 +3,22 @@ import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MGET';
|
||||
|
||||
describe('MGET', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('label=value'),
|
||||
['TS.MGET', 'FILTER', 'label=value']
|
||||
);
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('label=value'),
|
||||
['TS.MGET', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
|
||||
it('with LATEST', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('label=value', {
|
||||
LATEST: true
|
||||
}),
|
||||
['TS.MGET', 'LATEST', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mGet', async client => {
|
||||
|
@@ -1,10 +1,15 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { Filter, pushFilterArgument, RawLabels, SampleRawReply, SampleReply, transformSampleReply } from '.';
|
||||
import { Filter, pushFilterArgument, pushLatestArgument, RawLabels, SampleRawReply, SampleReply, transformSampleReply } from '.';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(filter: Filter): RedisCommandArguments {
|
||||
return pushFilterArgument(['TS.MGET'], filter);
|
||||
export interface MGetOptions {
|
||||
LATEST?: boolean;
|
||||
}
|
||||
|
||||
export function transformArguments(filter: Filter, options?: MGetOptions): RedisCommandArguments {
|
||||
const args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
||||
return pushFilterArgument(args, filter);
|
||||
}
|
||||
|
||||
export type MGetRawReply = Array<[
|
||||
|
@@ -7,12 +7,12 @@ import {
|
||||
Filter,
|
||||
pushFilterArgument
|
||||
} from '.';
|
||||
import { MGetRawReply, MGetReply } from './MGET';
|
||||
import { MGetOptions, MGetRawReply, MGetReply } from './MGET';
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
interface MGetWithLabelsOptions {
|
||||
interface MGetWithLabelsOptions extends MGetOptions {
|
||||
SELECTED_LABELS?: SelectedLabels;
|
||||
}
|
||||
|
||||
|
@@ -24,8 +24,8 @@ describe('MRANGE', () => {
|
||||
},
|
||||
}),
|
||||
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'sum']
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -25,8 +25,8 @@ describe('MRANGE_WITHLABELS', () => {
|
||||
},
|
||||
}),
|
||||
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1', 'SELECTED_LABELS', 'label',
|
||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'sum']
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -24,8 +24,8 @@ describe('MREVRANGE', () => {
|
||||
},
|
||||
}),
|
||||
['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'sum']
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -25,8 +25,8 @@ describe('MREVRANGE_WITHLABELS', () => {
|
||||
},
|
||||
}),
|
||||
['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1', 'SELECTED_LABELS', 'label',
|
||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'sum']
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'SELECTED_LABELS', 'label',
|
||||
'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -20,7 +20,7 @@ describe('RANGE', () => {
|
||||
}
|
||||
}),
|
||||
['TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1']
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
|
||||
|
@@ -59,7 +59,7 @@ describe('REVRANGE', () => {
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'avg', '1']
|
||||
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('REVRANGE', () => {
|
||||
}),
|
||||
[
|
||||
'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'avg', '1'
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
@@ -6,6 +6,7 @@ import {
|
||||
TimeSeriesEncoding,
|
||||
pushEncodingArgument,
|
||||
pushChunkSizeArgument,
|
||||
pushDuplicatePolicy,
|
||||
pushLabelsArgument,
|
||||
transformIncrDecrArguments,
|
||||
transformSampleReply,
|
||||
@@ -19,7 +20,10 @@ import {
|
||||
pushMRangeWithLabelsArguments,
|
||||
transformRangeReply,
|
||||
transformMRangeReply,
|
||||
transformMRangeWithLabelsReply
|
||||
transformMRangeWithLabelsReply,
|
||||
TimeSeriesDuplicatePolicies,
|
||||
pushLatestArgument,
|
||||
TimeSeriesBucketTimestamp
|
||||
} from '.';
|
||||
|
||||
describe('transformTimestampArgument', () => {
|
||||
@@ -87,6 +91,17 @@ describe('pushChunkSizeArgument', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('pushDuplicatePolicy', () => {
|
||||
testOptionalArgument(pushDuplicatePolicy);
|
||||
|
||||
it('BLOCK', () => {
|
||||
assert.deepEqual(
|
||||
pushDuplicatePolicy([], TimeSeriesDuplicatePolicies.BLOCK),
|
||||
['DUPLICATE_POLICY', 'BLOCK']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('pushLabelsArgument', () => {
|
||||
testOptionalArgument(pushLabelsArgument);
|
||||
|
||||
@@ -202,16 +217,44 @@ describe('pushRangeArguments', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('with AGGREGATION', () => {
|
||||
assert.deepEqual(
|
||||
pushRangeArguments([], '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.FIRST,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['-', '+', 'AGGREGATION', 'first', '1']
|
||||
);
|
||||
describe('with AGGREGATION', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
pushRangeArguments([], '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.FIRST,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['-', '+', 'AGGREGATION', 'FIRST', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with BUCKETTIMESTAMP', () => {
|
||||
assert.deepEqual(
|
||||
pushRangeArguments([], '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.FIRST,
|
||||
timeBucket: 1,
|
||||
BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW
|
||||
}
|
||||
}),
|
||||
['-', '+', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-']
|
||||
);
|
||||
});
|
||||
|
||||
it('with BUCKETTIMESTAMP', () => {
|
||||
assert.deepEqual(
|
||||
pushRangeArguments([], '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.FIRST,
|
||||
timeBucket: 1,
|
||||
EMPTY: true
|
||||
}
|
||||
}),
|
||||
['-', '+', 'AGGREGATION', 'FIRST', '1', 'EMPTY']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
|
||||
@@ -226,11 +269,13 @@ describe('pushRangeArguments', () => {
|
||||
ALIGN: 1,
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.FIRST,
|
||||
timeBucket: 1
|
||||
timeBucket: 1,
|
||||
BUCKETTIMESTAMP: TimeSeriesBucketTimestamp.LOW,
|
||||
EMPTY: true
|
||||
}
|
||||
}),
|
||||
['-', '+', 'FILTER_BY_TS', 'ts', 'FILTER_BY_VALUE', '1', '2',
|
||||
'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'first', '1']
|
||||
'COUNT', '1', 'ALIGN', '1', 'AGGREGATION', 'FIRST', '1', 'BUCKETTIMESTAMP', '-', 'EMPTY']
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -249,7 +294,7 @@ describe('pushMRangeGroupByArguments', () => {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.MAXIMUM
|
||||
}),
|
||||
['GROUPBY', 'label', 'REDUCE', 'max']
|
||||
['GROUPBY', 'label', 'REDUCE', 'MAX']
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -286,7 +331,7 @@ describe('pushMRangeArguments', () => {
|
||||
reducer: TimeSeriesReducers.MAXIMUM
|
||||
}
|
||||
}),
|
||||
['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'max']
|
||||
['-', '+', 'FILTER', 'label=value', 'GROUPBY', 'label', 'REDUCE', 'MAX']
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -369,3 +414,26 @@ describe('transformMRangeWithLabelsReply', () => {
|
||||
}]
|
||||
);
|
||||
});
|
||||
|
||||
describe('pushLatestArgument', () => {
|
||||
it('undefined', () => {
|
||||
assert.deepEqual(
|
||||
pushLatestArgument([]),
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('false', () => {
|
||||
assert.deepEqual(
|
||||
pushLatestArgument([], false),
|
||||
[]
|
||||
);
|
||||
});
|
||||
|
||||
it('true', () => {
|
||||
assert.deepEqual(
|
||||
pushLatestArgument([], true),
|
||||
['LATEST']
|
||||
);
|
||||
});
|
||||
})
|
||||
|
@@ -68,18 +68,25 @@ export default {
|
||||
};
|
||||
|
||||
export enum TimeSeriesAggregationType {
|
||||
AVERAGE = 'avg',
|
||||
SUM = 'sum',
|
||||
MINIMUM = 'min',
|
||||
MAXIMUM = 'max',
|
||||
RANGE = 'range',
|
||||
COUNT = 'count',
|
||||
FIRST = 'first',
|
||||
LAST = 'last',
|
||||
STD_P = 'std.p',
|
||||
STD_S = 'std.s',
|
||||
VAR_P = 'var.p',
|
||||
VAR_S = 'var.s'
|
||||
AVG = 'AVG',
|
||||
// @deprecated
|
||||
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 {
|
||||
@@ -92,9 +99,20 @@ export enum TimeSeriesDuplicatePolicies {
|
||||
}
|
||||
|
||||
export enum TimeSeriesReducers {
|
||||
SUM = 'sum',
|
||||
MINIMUM = 'min',
|
||||
MAXIMUM = 'max',
|
||||
AVG = 'AVG',
|
||||
SUM = 'SUM',
|
||||
MIN = 'MIN',
|
||||
// @deprecated
|
||||
MINIMUM = 'MIN',
|
||||
MAX = 'MAX',
|
||||
// @deprecated
|
||||
MAXIMUM = 'MAX',
|
||||
RANGE = 'range',
|
||||
COUNT = 'COUNT',
|
||||
STD_P = 'STD.P',
|
||||
STD_S = 'STD.S',
|
||||
VAR_P = 'VAR.P',
|
||||
VAR_S = 'VAR.S',
|
||||
}
|
||||
|
||||
export type Timestamp = number | Date | string;
|
||||
@@ -147,6 +165,17 @@ export function pushChunkSizeArgument(args: RedisCommandArguments, chunkSize?: n
|
||||
return args;
|
||||
}
|
||||
|
||||
export function pushDuplicatePolicy(args: RedisCommandArguments, duplicatePolicy?: TimeSeriesDuplicatePolicies): RedisCommandArguments {
|
||||
if (duplicatePolicy) {
|
||||
args.push(
|
||||
'DUPLICATE_POLICY',
|
||||
duplicatePolicy
|
||||
);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export type RawLabels = Array<[label: string, value: string]>;
|
||||
|
||||
export type Labels = {
|
||||
@@ -226,7 +255,14 @@ export function transformSampleReply(reply: SampleRawReply): SampleReply {
|
||||
};
|
||||
}
|
||||
|
||||
export enum TimeSeriesBucketTimestamp {
|
||||
LOW = '-',
|
||||
HIGH = '+',
|
||||
MID = '~'
|
||||
}
|
||||
|
||||
export interface RangeOptions {
|
||||
LATEST?: boolean;
|
||||
FILTER_BY_TS?: Array<Timestamp>;
|
||||
FILTER_BY_VALUE?: {
|
||||
min: number;
|
||||
@@ -237,6 +273,8 @@ export interface RangeOptions {
|
||||
AGGREGATION?: {
|
||||
type: TimeSeriesAggregationType;
|
||||
timeBucket: Timestamp;
|
||||
BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp;
|
||||
EMPTY?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -251,9 +289,11 @@ export function pushRangeArguments(
|
||||
transformTimestampArgument(toTimestamp)
|
||||
);
|
||||
|
||||
pushLatestArgument(args, options?.LATEST);
|
||||
|
||||
if (options?.FILTER_BY_TS) {
|
||||
args.push('FILTER_BY_TS');
|
||||
for(const ts of options.FILTER_BY_TS) {
|
||||
for (const ts of options.FILTER_BY_TS) {
|
||||
args.push(transformTimestampArgument(ts));
|
||||
}
|
||||
}
|
||||
@@ -286,6 +326,17 @@ export function pushRangeArguments(
|
||||
options.AGGREGATION.type,
|
||||
transformTimestampArgument(options.AGGREGATION.timeBucket)
|
||||
);
|
||||
|
||||
if (options.AGGREGATION.BUCKETTIMESTAMP) {
|
||||
args.push(
|
||||
'BUCKETTIMESTAMP',
|
||||
options.AGGREGATION.BUCKETTIMESTAMP
|
||||
);
|
||||
}
|
||||
|
||||
if (options.AGGREGATION.EMPTY) {
|
||||
args.push('EMPTY');
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
@@ -406,3 +457,11 @@ export function transformMRangeWithLabelsReply(reply: MRangeRawReply): Array<MRa
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export function pushLatestArgument(args: RedisCommandArguments, latest?: boolean): RedisCommandArguments {
|
||||
if (latest) {
|
||||
args.push('LATEST');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
Reference in New Issue
Block a user