You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-06 02:15:48 +03:00
WIP
This commit is contained in:
@@ -64,7 +64,7 @@ describe('TS.ALTER', () => {
|
||||
testUtils.testWithClient('client.ts.alter', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.create('key'),
|
||||
client.ts.alter('key', { RETENTION: 1 })
|
||||
client.ts.alter('key')
|
||||
]);
|
||||
|
||||
assert.equal(reply, 'OK');
|
||||
|
@@ -3,7 +3,7 @@ import testUtils, { GLOBAL } from '../test-utils';
|
||||
import MADD from './MADD';
|
||||
import { SimpleError } from '@redis/client/lib/errors';
|
||||
|
||||
describe.only('TS.MADD', () => {
|
||||
describe('TS.MADD', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
MADD.transformArguments([{
|
||||
|
@@ -1,40 +1,40 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MGET';
|
||||
import MGET from './MGET';
|
||||
|
||||
describe('TS.MGET', () => {
|
||||
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']
|
||||
);
|
||||
});
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
MGET.transformArguments('label=value'),
|
||||
['TS.MGET', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mGet', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
});
|
||||
it('with LATEST', () => {
|
||||
assert.deepEqual(
|
||||
MGET.transformArguments('label=value', {
|
||||
LATEST: true
|
||||
}),
|
||||
['TS.MGET', 'LATEST', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mGet('label=value'),
|
||||
[{
|
||||
key: 'key',
|
||||
sample: {
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
testUtils.testWithClient('client.ts.mGet', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
}),
|
||||
client.ts.mGet('label=value')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
key: 'key',
|
||||
sample: {
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,31 +1,31 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { Filter, pushFilterArgument, pushLatestArgument, RawLabels, SampleRawReply, SampleReply, transformSampleReply } from '.';
|
||||
import { CommandArguments, Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export interface MGetOptions {
|
||||
LATEST?: boolean;
|
||||
export interface TsMGetOptions {
|
||||
LATEST?: boolean;
|
||||
}
|
||||
|
||||
export function transformArguments(filter: Filter, options?: MGetOptions): RedisCommandArguments {
|
||||
export function pushLatestArgument(args: CommandArguments, latest?: boolean) {
|
||||
if (latest) {
|
||||
args.push('LATEST');
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export function pushFilterArgument(args: CommandArguments, filter: RedisVariadicArgument) {
|
||||
args.push('FILTER');
|
||||
return pushVariadicArguments(args, filter);
|
||||
}
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(filter: RedisVariadicArgument, options?: TsMGetOptions) {
|
||||
const args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
||||
return pushFilterArgument(args, filter);
|
||||
}
|
||||
|
||||
export type MGetRawReply = Array<[
|
||||
key: string,
|
||||
labels: RawLabels,
|
||||
sample: SampleRawReply
|
||||
]>;
|
||||
|
||||
export interface MGetReply {
|
||||
key: string,
|
||||
sample: SampleReply
|
||||
}
|
||||
|
||||
export function transformReply(reply: MGetRawReply): Array<MGetReply> {
|
||||
return reply.map(([key, _, sample]) => ({
|
||||
key,
|
||||
sample: transformSampleReply(sample)
|
||||
}));
|
||||
}
|
||||
},
|
||||
// TODO
|
||||
// transformSampleReply
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,39 +1,41 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MGET_WITHLABELS';
|
||||
import MGET_WITHLABELS from './MGET_WITHLABELS';
|
||||
|
||||
describe('TS.MGET_WITHLABELS', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('label=value'),
|
||||
['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
|
||||
it('with SELECTED_LABELS', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('label=value', { SELECTED_LABELS: 'label' }),
|
||||
['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
MGET_WITHLABELS.transformArguments('label=value'),
|
||||
['TS.MGET', 'WITHLABELS', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mGetWithLabels', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
});
|
||||
it('with SELECTED_LABELS', () => {
|
||||
assert.deepEqual(
|
||||
MGET_WITHLABELS.transformArguments('label=value', {
|
||||
SELECTED_LABELS: 'label'
|
||||
}),
|
||||
['TS.MGET', 'SELECTED_LABELS', 'label', 'FILTER', 'label=value']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mGetWithLabels('label=value'),
|
||||
[{
|
||||
key: 'key',
|
||||
labels: { label: 'value'},
|
||||
sample: {
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
testUtils.testWithClient('client.ts.mGetWithLabels', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
}),
|
||||
client.ts.mGetWithLabels('label=value')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
key: 'key',
|
||||
labels: { label: 'value' },
|
||||
sample: {
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,37 +1,20 @@
|
||||
import {
|
||||
SelectedLabels,
|
||||
pushWithLabelsArgument,
|
||||
Labels,
|
||||
transformLablesReply,
|
||||
transformSampleReply,
|
||||
Filter,
|
||||
pushFilterArgument
|
||||
} from '.';
|
||||
import { MGetOptions, MGetRawReply, MGetReply } from './MGET';
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { TsMGetOptions, pushLatestArgument, pushFilterArgument } from './MGET';
|
||||
import { pushWithLabelsArgument } from '.';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
interface MGetWithLabelsOptions extends MGetOptions {
|
||||
SELECTED_LABELS?: SelectedLabels;
|
||||
export interface TsMGetWithLabelsOptions extends TsMGetOptions {
|
||||
SELECTED_LABELS?: RedisVariadicArgument;
|
||||
}
|
||||
|
||||
export function transformArguments(
|
||||
filter: Filter,
|
||||
options?: MGetWithLabelsOptions
|
||||
): RedisCommandArguments {
|
||||
const args = pushWithLabelsArgument(['TS.MGET'], options?.SELECTED_LABELS);
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(filter: RedisVariadicArgument, options?: TsMGetWithLabelsOptions) {
|
||||
let args = pushLatestArgument(['TS.MGET'], options?.LATEST);
|
||||
args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
|
||||
return pushFilterArgument(args, filter);
|
||||
}
|
||||
|
||||
export interface MGetWithLabelsReply extends MGetReply {
|
||||
labels: Labels;
|
||||
};
|
||||
|
||||
export function transformReply(reply: MGetRawReply): Array<MGetWithLabelsReply> {
|
||||
return reply.map(([key, labels, sample]) => ({
|
||||
key,
|
||||
labels: transformLablesReply(labels),
|
||||
sample: transformSampleReply(sample)
|
||||
}));
|
||||
}
|
||||
},
|
||||
// TODO
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,50 +1,54 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MRANGE';
|
||||
import MRANGE from './MRANGE';
|
||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||
|
||||
describe('TS.MRANGE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
['TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
MRANGE.transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
[
|
||||
'TS.MRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mRange', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value'}
|
||||
});
|
||||
testUtils.testWithClient('client.ts.mRange', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 0, {
|
||||
LABELS: {
|
||||
label: 'value'
|
||||
}
|
||||
}),
|
||||
client.ts.mRange('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
})
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mRange('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
}),
|
||||
[{
|
||||
key: 'key',
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(reply, [{
|
||||
key: 'key',
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,21 +1,68 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.';
|
||||
import { RedisArgument, Command, CommandArguments } from '@redis/client/dist/lib/RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { Timestamp } from '.';
|
||||
import { TsRangeOptions, pushRangeArguments } from './RANGE';
|
||||
import { pushFilterArgument } from './MGET';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
export const TIME_SERIES_REDUCERS = {
|
||||
AVG: 'AVG',
|
||||
SUM: 'SUM',
|
||||
MIN: 'MIN',
|
||||
MAX: 'MAX',
|
||||
RANGE: 'RANGE',
|
||||
COUNT: 'COUNT',
|
||||
STD_P: 'STD.P',
|
||||
STD_S: 'STD.S',
|
||||
VAR_P: 'VAR.P',
|
||||
VAR_S: 'VAR.S'
|
||||
};
|
||||
|
||||
export function transformArguments(
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filters: Filter,
|
||||
options?: MRangeOptions
|
||||
): RedisCommandArguments {
|
||||
return pushMRangeArguments(
|
||||
['TS.MRANGE'],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
filters,
|
||||
options
|
||||
);
|
||||
export type TimeSeriesReducers = typeof TIME_SERIES_REDUCERS[keyof typeof TIME_SERIES_REDUCERS];
|
||||
|
||||
export interface TsMRangeOptions extends TsRangeOptions {
|
||||
GROUPBY?: {
|
||||
label: RedisArgument;
|
||||
reducer: TimeSeriesReducers;
|
||||
};
|
||||
}
|
||||
|
||||
export { transformMRangeReply as transformReply } from '.';
|
||||
export function pushGroupByArgument(args: CommandArguments, groupBy?: TsMRangeOptions['GROUPBY']) {
|
||||
if (groupBy) {
|
||||
args.push(
|
||||
'GROUPBY',
|
||||
groupBy.label,
|
||||
'REDUCE',
|
||||
groupBy.reducer
|
||||
);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
export function transformMRangeArguments(
|
||||
command: RedisArgument,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filter: RedisVariadicArgument,
|
||||
options?: TsMRangeOptions
|
||||
) {
|
||||
let args = pushRangeArguments(
|
||||
[command],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
options
|
||||
);
|
||||
|
||||
args = pushFilterArgument(args, filter);
|
||||
|
||||
return pushGroupByArgument(args, options?.GROUPBY);
|
||||
}
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments: transformMRangeArguments.bind(undefined, 'TS.MRANGE'),
|
||||
// TODO
|
||||
// export { transformMRangeReply as transformReply } from '.';
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,52 +1,53 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MRANGE_WITHLABELS';
|
||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||
import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
||||
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
||||
import { TIME_SERIES_REDUCERS } from './MRANGE';
|
||||
|
||||
describe('TS.MRANGE_WITHLABELS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
SELECTED_LABELS: ['label'],
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
['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']
|
||||
);
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
MRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
SELECTED_LABELS: ['label'],
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TIME_SERIES_AGGREGATION_TYPE.AVG,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TIME_SERIES_REDUCERS.SUM
|
||||
},
|
||||
}),
|
||||
['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']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mRangeWithLabels', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mRangeWithLabels', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value'}
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mRangeWithLabels('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
}),
|
||||
[{
|
||||
key: 'key',
|
||||
labels: { label: 'value' },
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(
|
||||
await client.ts.mRangeWithLabels('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
}),
|
||||
[{
|
||||
key: 'key',
|
||||
labels: { label: 'value' },
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,21 +1,32 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments } from '.';
|
||||
import { RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { RedisVariadicArgument } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { TsMRangeOptions, pushGroupByArgument } from './MRANGE';
|
||||
import { Timestamp, pushWithLabelsArgument } from '.';
|
||||
import { pushFilterArgument } from './MGET';
|
||||
import { pushRangeArguments } from './RANGE';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filters: string | Array<string>,
|
||||
options?: MRangeWithLabelsOptions
|
||||
): RedisCommandArguments {
|
||||
return pushMRangeWithLabelsArguments(
|
||||
['TS.MRANGE'],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
filters,
|
||||
options
|
||||
);
|
||||
export interface TsMRangeWithLabelsOptions extends TsMRangeOptions {
|
||||
SELECTED_LABELS?: RedisVariadicArgument;
|
||||
}
|
||||
|
||||
export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||
export function transformMRangeWithLabelsArguments(
|
||||
command: RedisArgument,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filter: RedisVariadicArgument,
|
||||
options?: TsMRangeWithLabelsOptions
|
||||
) {
|
||||
let args = pushRangeArguments([command], fromTimestamp, toTimestamp, options);
|
||||
args = pushWithLabelsArgument(args, options?.SELECTED_LABELS);
|
||||
args = pushFilterArgument(args, filter);
|
||||
return pushGroupByArgument(args, options?.GROUPBY);
|
||||
}
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MRANGE'),
|
||||
// TODO
|
||||
// export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
@@ -4,47 +4,49 @@ import { transformArguments } from './MREVRANGE';
|
||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||
|
||||
describe('TS.MREVRANGE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
['TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM']
|
||||
);
|
||||
});
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
[
|
||||
'TS.MREVRANGE', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE', '0', '1',
|
||||
'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1', 'FILTER', 'label=value',
|
||||
'GROUPBY', 'label', 'REDUCE', 'SUM'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mRevRange', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value'}
|
||||
});
|
||||
testUtils.testWithClient('client.ts.mRevRange', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
}),
|
||||
client.ts.mRevRange('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
})
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mRevRange('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
}),
|
||||
[{
|
||||
key: 'key',
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(reply, [{
|
||||
key: 'key',
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,21 +1,9 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { MRangeOptions, Timestamp, pushMRangeArguments, Filter } from '.';
|
||||
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import MRANGE, { transformMRangeArguments } from './MRANGE';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filters: Filter,
|
||||
options?: MRangeOptions
|
||||
): RedisCommandArguments {
|
||||
return pushMRangeArguments(
|
||||
['TS.MREVRANGE'],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
filters,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
export { transformMRangeReply as transformReply } from '.';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: MRANGE.FIRST_KEY_INDEX,
|
||||
IS_READ_ONLY: MRANGE.IS_READ_ONLY,
|
||||
transformArguments: transformMRangeArguments.bind(undefined, 'TS.MREVRANGE'),
|
||||
transformReply: MRANGE.transformReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,52 +1,54 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './MREVRANGE_WITHLABELS';
|
||||
import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
||||
import { TimeSeriesAggregationType, TimeSeriesReducers } from '.';
|
||||
|
||||
describe('TS.MREVRANGE_WITHLABELS', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
SELECTED_LABELS: ['label'],
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
['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']
|
||||
);
|
||||
});
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
MREVRANGE_WITHLABELS.transformArguments('-', '+', 'label=value', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 0,
|
||||
max: 1
|
||||
},
|
||||
SELECTED_LABELS: ['label'],
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
},
|
||||
GROUPBY: {
|
||||
label: 'label',
|
||||
reducer: TimeSeriesReducers.SUM
|
||||
},
|
||||
}),
|
||||
[
|
||||
'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'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => {
|
||||
await client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value'}
|
||||
});
|
||||
testUtils.testWithClient('client.ts.mRevRangeWithLabels', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 0, {
|
||||
LABELS: { label: 'value' }
|
||||
}),
|
||||
client.ts.mRevRangeWithLabels('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
})
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.mRevRangeWithLabels('-', '+', 'label=value', {
|
||||
COUNT: 1
|
||||
}),
|
||||
[{
|
||||
key: 'key',
|
||||
labels: { label: 'value' },
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(reply, [{
|
||||
key: 'key',
|
||||
labels: { label: 'value' },
|
||||
samples: [{
|
||||
timestamp: 0,
|
||||
value: 0
|
||||
}]
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,21 +1,11 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { Timestamp, MRangeWithLabelsOptions, pushMRangeWithLabelsArguments, Filter } from '.';
|
||||
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { transformMRangeWithLabelsArguments } from './MRANGE_WITHLABELS';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
filters: Filter,
|
||||
options?: MRangeWithLabelsOptions
|
||||
): RedisCommandArguments {
|
||||
return pushMRangeWithLabelsArguments(
|
||||
['TS.MREVRANGE'],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
filters,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments: transformMRangeWithLabelsArguments.bind(undefined, 'TS.MREVRANGE'),
|
||||
// TODO
|
||||
// export { transformMRangeWithLabelsReply as transformReply } from '.';
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,34 +1,34 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './QUERYINDEX';
|
||||
import QUERYINDEX from './QUERYINDEX';
|
||||
|
||||
describe('TS.QUERYINDEX', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('single filter', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('*'),
|
||||
['TS.QUERYINDEX', '*']
|
||||
);
|
||||
});
|
||||
|
||||
it('multiple filters', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments(['a=1', 'b=2']),
|
||||
['TS.QUERYINDEX', 'a=1', 'b=2']
|
||||
);
|
||||
});
|
||||
describe('transformArguments', () => {
|
||||
it('single filter', () => {
|
||||
assert.deepEqual(
|
||||
QUERYINDEX.transformArguments('*'),
|
||||
['TS.QUERYINDEX', '*']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.queryIndex', async client => {
|
||||
await client.ts.create('key', {
|
||||
LABELS: {
|
||||
label: 'value'
|
||||
}
|
||||
});
|
||||
it('multiple filters', () => {
|
||||
assert.deepEqual(
|
||||
QUERYINDEX.transformArguments(['a=1', 'b=2']),
|
||||
['TS.QUERYINDEX', 'a=1', 'b=2']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.queryIndex('label=value'),
|
||||
['key']
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
testUtils.testWithClient('client.ts.queryIndex', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.create('key', {
|
||||
LABELS: {
|
||||
label: 'value'
|
||||
}
|
||||
}),
|
||||
client.ts.queryIndex('label=value')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, ['key']);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,11 +1,14 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
import { Filter } from '.';
|
||||
import { ArrayReply, BlobStringReply, SetReply, Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(filter: Filter): RedisCommandArguments {
|
||||
export default {
|
||||
FIRST_KEY_INDEX: undefined,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments(filter: RedisVariadicArgument) {
|
||||
return pushVariadicArguments(['TS.QUERYINDEX'], filter);
|
||||
}
|
||||
|
||||
export declare function transformReply(): Array<string>;
|
||||
},
|
||||
transformReply: {
|
||||
2: undefined as unknown as () => ArrayReply<BlobStringReply>,
|
||||
3: undefined as unknown as () => SetReply<BlobStringReply>
|
||||
}
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,38 +1,40 @@
|
||||
import { strict as assert } from 'assert';
|
||||
import testUtils, { GLOBAL } from '../test-utils';
|
||||
import { transformArguments } from './RANGE';
|
||||
import { TimeSeriesAggregationType } from '.';
|
||||
import RANGE from './RANGE';
|
||||
import { TIME_SERIES_AGGREGATION_TYPE } from './CREATERULE';
|
||||
|
||||
describe('TS.RANGE', () => {
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
it('transformArguments', () => {
|
||||
assert.deepEqual(
|
||||
RANGE.transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TIME_SERIES_AGGREGATION_TYPE.AVG,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
[
|
||||
'TS.RANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||
]
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.range', async client => {
|
||||
await client.ts.add('key', 1, 2);
|
||||
testUtils.testWithClient('client.ts.range', async client => {
|
||||
const [, reply] = await Promise.all([
|
||||
client.ts.add('key', 1, 2),
|
||||
client.ts.range('key', '-', '+')
|
||||
]);
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.range('key', '-', '+'),
|
||||
[{
|
||||
timestamp: 1,
|
||||
value: 2
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
assert.deepEqual(reply, [{
|
||||
timestamp: 1,
|
||||
value: 2
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,24 +1,117 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.';
|
||||
import { CommandArguments, RedisArgument, Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import { Timestamp, transformTimestampArgument } from '.';
|
||||
import { TimeSeriesAggregationType } from './CREATERULE';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
export const TIME_SERIES_BUCKET_TIMESTAMP = {
|
||||
LOW: '-',
|
||||
MIDDLE: '~',
|
||||
END: '+'
|
||||
};
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
export type TimeSeriesBucketTimestamp = typeof TIME_SERIES_BUCKET_TIMESTAMP[keyof typeof TIME_SERIES_BUCKET_TIMESTAMP];
|
||||
|
||||
export function transformArguments(
|
||||
key: string,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
options?: RangeOptions
|
||||
): RedisCommandArguments {
|
||||
return pushRangeArguments(
|
||||
['TS.RANGE', key],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
options
|
||||
export interface TsRangeOptions {
|
||||
LATEST?: boolean;
|
||||
FILTER_BY_TS?: Array<Timestamp>;
|
||||
FILTER_BY_VALUE?: {
|
||||
min: number;
|
||||
max: number;
|
||||
};
|
||||
COUNT?: number;
|
||||
ALIGN?: Timestamp;
|
||||
AGGREGATION?: {
|
||||
ALIGN?: Timestamp;
|
||||
type: TimeSeriesAggregationType;
|
||||
timeBucket: Timestamp;
|
||||
BUCKETTIMESTAMP?: TimeSeriesBucketTimestamp;
|
||||
EMPTY?: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
export function pushRangeArguments(
|
||||
args: CommandArguments,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
options?: TsRangeOptions
|
||||
) {
|
||||
args.push(
|
||||
transformTimestampArgument(fromTimestamp),
|
||||
transformTimestampArgument(toTimestamp)
|
||||
);
|
||||
|
||||
if (options?.LATEST) {
|
||||
args.push('LATEST');
|
||||
}
|
||||
|
||||
if (options?.FILTER_BY_TS) {
|
||||
args.push('FILTER_BY_TS');
|
||||
for (const timestamp of options.FILTER_BY_TS) {
|
||||
args.push(transformTimestampArgument(timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
if (options?.FILTER_BY_VALUE) {
|
||||
args.push(
|
||||
'FILTER_BY_VALUE',
|
||||
options.FILTER_BY_VALUE.min.toString(),
|
||||
options.FILTER_BY_VALUE.max.toString()
|
||||
);
|
||||
}
|
||||
|
||||
if (options?.COUNT !== undefined) {
|
||||
args.push('COUNT', options.COUNT.toString());
|
||||
}
|
||||
|
||||
if (options?.AGGREGATION) {
|
||||
if (options?.ALIGN !== undefined) {
|
||||
args.push('ALIGN', transformTimestampArgument(options.ALIGN));
|
||||
}
|
||||
|
||||
args.push(
|
||||
'AGGREGATION',
|
||||
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;
|
||||
}
|
||||
|
||||
export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
||||
return transformRangeReply(reply);
|
||||
export function transformRangeArguments(
|
||||
command: RedisArgument,
|
||||
key: RedisArgument,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
options?: TsRangeOptions
|
||||
) {
|
||||
return pushRangeArguments(
|
||||
[command, key],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
export default {
|
||||
FIRST_KEY_INDEX: 1,
|
||||
IS_READ_ONLY: true,
|
||||
transformArguments: transformRangeArguments.bind(undefined, 'TS.RANGE'),
|
||||
// TODO
|
||||
// import { SampleReply, transformRangeReply } from '.';
|
||||
// export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
||||
// return transformRangeReply(reply);
|
||||
// }
|
||||
transformReply: undefined as unknown as () => any
|
||||
} as const satisfies Command;
|
||||
|
||||
|
@@ -4,103 +4,101 @@ import { transformArguments } from './REVRANGE';
|
||||
import { TimeSeriesAggregationType } from '.';
|
||||
|
||||
describe('TS.REVRANGE', () => {
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+'),
|
||||
['TS.REVRANGE', 'key', '-', '+']
|
||||
);
|
||||
});
|
||||
|
||||
it('with FILTER_BY_TS', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0]
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0']
|
||||
);
|
||||
});
|
||||
|
||||
it('with FILTER_BY_VALUE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
}
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2']
|
||||
);
|
||||
});
|
||||
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
COUNT: 1
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with ALIGN', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
ALIGN: '-'
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-']
|
||||
);
|
||||
});
|
||||
|
||||
it('with AGGREGATION', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
[
|
||||
'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||
]
|
||||
);
|
||||
});
|
||||
describe('transformArguments', () => {
|
||||
it('without options', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+'),
|
||||
['TS.REVRANGE', 'key', '-', '+']
|
||||
);
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.revRange', async client => {
|
||||
await Promise.all([
|
||||
client.ts.add('key', 0, 1),
|
||||
client.ts.add('key', 1, 2)
|
||||
]);
|
||||
it('with FILTER_BY_TS', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0]
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0']
|
||||
);
|
||||
});
|
||||
|
||||
assert.deepEqual(
|
||||
await client.ts.revRange('key', '-', '+'),
|
||||
[{
|
||||
timestamp: 1,
|
||||
value: 2
|
||||
}, {
|
||||
timestamp: 0,
|
||||
value: 1
|
||||
}]
|
||||
);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
it('with FILTER_BY_VALUE', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
}
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_VALUE', '1', '2']
|
||||
);
|
||||
});
|
||||
|
||||
it('with COUNT', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
COUNT: 1
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'COUNT', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with ALIGN', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
ALIGN: '-'
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'ALIGN', '-']
|
||||
);
|
||||
});
|
||||
|
||||
it('with AGGREGATION', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
['TS.REVRANGE', 'key', '-', '+', 'AGGREGATION', 'AVG', '1']
|
||||
);
|
||||
});
|
||||
|
||||
it('with FILTER_BY_TS, FILTER_BY_VALUE, COUNT, ALIGN, AGGREGATION', () => {
|
||||
assert.deepEqual(
|
||||
transformArguments('key', '-', '+', {
|
||||
FILTER_BY_TS: [0],
|
||||
FILTER_BY_VALUE: {
|
||||
min: 1,
|
||||
max: 2
|
||||
},
|
||||
COUNT: 1,
|
||||
ALIGN: '-',
|
||||
AGGREGATION: {
|
||||
type: TimeSeriesAggregationType.AVERAGE,
|
||||
timeBucket: 1
|
||||
}
|
||||
}),
|
||||
[
|
||||
'TS.REVRANGE', 'key', '-', '+', 'FILTER_BY_TS', '0', 'FILTER_BY_VALUE',
|
||||
'1', '2', 'COUNT', '1', 'ALIGN', '-', 'AGGREGATION', 'AVG', '1'
|
||||
]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
testUtils.testWithClient('client.ts.revRange', async client => {
|
||||
const [, , reply] = await Promise.all([
|
||||
client.ts.add('key', 0, 1),
|
||||
client.ts.add('key', 1, 2),
|
||||
client.ts.revRange('key', '-', '+')
|
||||
]);
|
||||
|
||||
assert.deepEqual(reply, [{
|
||||
timestamp: 1,
|
||||
value: 2
|
||||
}, {
|
||||
timestamp: 0,
|
||||
value: 1
|
||||
}]);
|
||||
}, GLOBAL.SERVERS.OPEN);
|
||||
});
|
||||
|
@@ -1,24 +1,9 @@
|
||||
import { RedisCommandArguments } from '@redis/client/dist/lib/commands';
|
||||
import { RangeOptions, Timestamp, pushRangeArguments, SampleRawReply, SampleReply, transformRangeReply } from '.';
|
||||
import { Command } from '@redis/client/dist/lib/RESP/types';
|
||||
import RANGE, { transformRangeArguments } from './RANGE';
|
||||
|
||||
export const FIRST_KEY_INDEX = 1;
|
||||
|
||||
export const IS_READ_ONLY = true;
|
||||
|
||||
export function transformArguments(
|
||||
key: string,
|
||||
fromTimestamp: Timestamp,
|
||||
toTimestamp: Timestamp,
|
||||
options?: RangeOptions
|
||||
): RedisCommandArguments {
|
||||
return pushRangeArguments(
|
||||
['TS.REVRANGE', key],
|
||||
fromTimestamp,
|
||||
toTimestamp,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
export function transformReply(reply: Array<SampleRawReply>): Array<SampleReply> {
|
||||
return transformRangeReply(reply);
|
||||
}
|
||||
export default {
|
||||
FIRST_KEY_INDEX: RANGE.FIRST_KEY_INDEX,
|
||||
IS_READ_ONLY: RANGE.IS_READ_ONLY,
|
||||
transformArguments: transformRangeArguments.bind(undefined, 'TS.REVRANGE'),
|
||||
transformReply: RANGE.transformReply
|
||||
} as const satisfies Command;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { RedisArgument, RedisCommands } from '@redis/client/dist/lib/RESP/types';
|
||||
import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } from '@redis/client/dist/lib/RESP/types';
|
||||
import ADD from './ADD';
|
||||
import ALTER from './ALTER';
|
||||
import CREATE from './CREATE';
|
||||
@@ -11,15 +11,16 @@ import INCRBY from './INCRBY';
|
||||
// import INFO_DEBUG from './INFO_DEBUG';
|
||||
// import INFO from './INFO';
|
||||
import MADD from './MADD';
|
||||
// import MGET from './MGET';
|
||||
// import MGET_WITHLABELS from './MGET_WITHLABELS';
|
||||
// import QUERYINDEX from './QUERYINDEX';
|
||||
// import RANGE from './RANGE';
|
||||
// import REVRANGE from './REVRANGE';
|
||||
// import MRANGE from './MRANGE';
|
||||
// import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
||||
// import MREVRANGE from './MREVRANGE';
|
||||
// import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
||||
import MGET_WITHLABELS from './MGET_WITHLABELS';
|
||||
import MGET from './MGET';
|
||||
import MRANGE_WITHLABELS from './MRANGE_WITHLABELS';
|
||||
import MRANGE from './MRANGE';
|
||||
import MREVRANGE_WITHLABELS from './MREVRANGE_WITHLABELS';
|
||||
import MREVRANGE from './MREVRANGE';
|
||||
import QUERYINDEX from './QUERYINDEX';
|
||||
import RANGE from './RANGE';
|
||||
import REVRANGE from './REVRANGE';
|
||||
import { RedisVariadicArgument, pushVariadicArguments } from '@redis/client/dist/lib/commands/generic-transformers';
|
||||
|
||||
export default {
|
||||
ADD,
|
||||
@@ -46,24 +47,24 @@ export default {
|
||||
// info: INFO,
|
||||
MADD,
|
||||
mAdd: MADD,
|
||||
// MGET,
|
||||
// mGet: MGET,
|
||||
// MGET_WITHLABELS,
|
||||
// mGetWithLabels: MGET_WITHLABELS,
|
||||
// QUERYINDEX,
|
||||
// queryIndex: QUERYINDEX,
|
||||
// RANGE,
|
||||
// range: RANGE,
|
||||
// REVRANGE,
|
||||
// revRange: REVRANGE,
|
||||
// MRANGE,
|
||||
// mRange: MRANGE,
|
||||
// MRANGE_WITHLABELS,
|
||||
// mRangeWithLabels: MRANGE_WITHLABELS,
|
||||
// MREVRANGE,
|
||||
// mRevRange: MREVRANGE,
|
||||
// MREVRANGE_WITHLABELS,
|
||||
// mRevRangeWithLabels: MREVRANGE_WITHLABELS
|
||||
MGET_WITHLABELS,
|
||||
mGetWithLabels: MGET_WITHLABELS,
|
||||
MGET,
|
||||
mGet: MGET,
|
||||
MRANGE_WITHLABELS,
|
||||
mRangeWithLabels: MRANGE_WITHLABELS,
|
||||
MRANGE,
|
||||
mRange: MRANGE,
|
||||
MREVRANGE_WITHLABELS,
|
||||
mRevRangeWithLabels: MREVRANGE_WITHLABELS,
|
||||
MREVRANGE,
|
||||
mRevRange: MREVRANGE,
|
||||
QUERYINDEX,
|
||||
queryIndex: QUERYINDEX,
|
||||
RANGE,
|
||||
range: RANGE,
|
||||
REVRANGE,
|
||||
revRange: REVRANGE
|
||||
} as const satisfies RedisCommands;
|
||||
|
||||
export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
|
||||
@@ -148,20 +149,22 @@ export function pushLabelsArgument(args: Array<RedisArgument>, labels?: Labels)
|
||||
// return labels
|
||||
// }
|
||||
|
||||
|
||||
// export type SampleRawReply = [timestamp: number, value: string];
|
||||
|
||||
// export interface SampleReply {
|
||||
// timestamp: number;
|
||||
// value: number;
|
||||
// }
|
||||
|
||||
// export function transformSampleReply(reply: SampleRawReply): SampleReply {
|
||||
// return {
|
||||
// timestamp: reply[0],
|
||||
// value: Number(reply[1])
|
||||
// };
|
||||
// }
|
||||
export const transformSampleReply = {
|
||||
2(reply: TuplesReply<[timestamp: NumberReply, value: BlobStringReply]>) {
|
||||
const [timestamp, value] = reply as unknown as UnwrapReply<typeof reply>;
|
||||
return {
|
||||
timestamp,
|
||||
value: Number(value)
|
||||
};
|
||||
},
|
||||
3(reply: TuplesReply<[timestamp: NumberReply, value: DoubleReply]>) {
|
||||
const [timestamp, value] = reply as unknown as UnwrapReply<typeof reply>;
|
||||
return {
|
||||
timestamp,
|
||||
value
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// export enum TimeSeriesBucketTimestamp {
|
||||
// LOW = '-',
|
||||
@@ -293,16 +296,15 @@ export function pushLabelsArgument(args: Array<RedisArgument>, labels?: Labels)
|
||||
|
||||
// export type SelectedLabels = string | Array<string>;
|
||||
|
||||
// export function pushWithLabelsArgument(args: RedisCommandArguments, selectedLabels?: SelectedLabels): RedisCommandArguments {
|
||||
// if (!selectedLabels) {
|
||||
// args.push('WITHLABELS');
|
||||
// } else {
|
||||
// args.push('SELECTED_LABELS');
|
||||
// args = pushVariadicArguments(args, selectedLabels);
|
||||
// }
|
||||
|
||||
// return args;
|
||||
// }
|
||||
export function pushWithLabelsArgument(args: CommandArguments, selectedLabels?: RedisVariadicArgument) {
|
||||
if (!selectedLabels) {
|
||||
args.push('WITHLABELS');
|
||||
return args;
|
||||
} else {
|
||||
args.push('SELECTED_LABELS');
|
||||
return pushVariadicArguments(args, selectedLabels);
|
||||
}
|
||||
}
|
||||
|
||||
// export interface MRangeWithLabelsOptions extends MRangeOptions {
|
||||
// SELECTED_LABELS?: SelectedLabels;
|
||||
|
@@ -4,8 +4,8 @@ export {
|
||||
TIME_SERIES_ENCODING,
|
||||
TimeSeriesEncoding,
|
||||
TIME_SERIES_DUPLICATE_POLICIES,
|
||||
TimeSeriesDuplicatePolicies,
|
||||
// TimeSeriesBucketTimestamp
|
||||
TimeSeriesDuplicatePolicies
|
||||
} from './commands';
|
||||
|
||||
export { TIME_SERIES_AGGREGATION_TYPE, TimeSeriesAggregationType } from './commands/CREATERULE';
|
||||
export { TIME_SERIES_BUCKET_TIMESTAMP, TimeSeriesBucketTimestamp } from './commands/RANGE';
|
||||
|
@@ -5,7 +5,8 @@
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist/"
|
||||
"dist/",
|
||||
"!dist/tsconfig.tsbuildinfo"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "nyc -r text-summary -r lcov mocha -r source-map-support/register -r ts-node/register './lib/**/*.spec.ts'"
|
||||
|
Reference in New Issue
Block a user