You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-07 13:22:56 +03:00
CAE-193: add "IGNORE" options to time series commands (for v5 branch) (#2753)
* CAE-193: add "IGNORE" options to time series commands (for v5 branch) * add INCR/DECR and modify tests to not test ignore on older version * require maxTimeDiff/maxValDiff to be specified also rename them * fix add/ignore test after api change * update tests for api change in IGNORE option
This commit is contained in:
@@ -57,16 +57,29 @@ describe('TS.ADD', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS', () => {
|
it ('with IGNORE', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
ADD.transformArguments('key', '*', 1, {
|
||||||
|
IGNORE: {
|
||||||
|
maxTimeDiff: 1,
|
||||||
|
maxValDiff: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.ADD', 'key', '*', '1', 'IGNORE', '1', '1']
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with RETENTION, ENCODING, CHUNK_SIZE, ON_DUPLICATE, LABELS, IGNORE', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
ADD.transformArguments('key', '*', 1, {
|
ADD.transformArguments('key', '*', 1, {
|
||||||
RETENTION: 1,
|
RETENTION: 1,
|
||||||
ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
|
ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
|
||||||
CHUNK_SIZE: 1,
|
CHUNK_SIZE: 1,
|
||||||
ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
ON_DUPLICATE: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
||||||
LABELS: { label: 'value' }
|
LABELS: { label: 'value' },
|
||||||
|
IGNORE: { maxTimeDiff: 1, maxValDiff: 1}
|
||||||
}),
|
}),
|
||||||
['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value']
|
['TS.ADD', 'key', '*', '1', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'ON_DUPLICATE', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -8,15 +8,22 @@ import {
|
|||||||
TimeSeriesDuplicatePolicies,
|
TimeSeriesDuplicatePolicies,
|
||||||
Labels,
|
Labels,
|
||||||
pushLabelsArgument,
|
pushLabelsArgument,
|
||||||
Timestamp
|
Timestamp,
|
||||||
|
pushIgnoreArgument
|
||||||
} from '.';
|
} from '.';
|
||||||
|
|
||||||
|
export interface TsIgnoreOptions {
|
||||||
|
maxTimeDiff: number;
|
||||||
|
maxValDiff: number;
|
||||||
|
}
|
||||||
|
|
||||||
export interface TsAddOptions {
|
export interface TsAddOptions {
|
||||||
RETENTION?: number;
|
RETENTION?: number;
|
||||||
ENCODING?: TimeSeriesEncoding;
|
ENCODING?: TimeSeriesEncoding;
|
||||||
CHUNK_SIZE?: number;
|
CHUNK_SIZE?: number;
|
||||||
ON_DUPLICATE?: TimeSeriesDuplicatePolicies;
|
ON_DUPLICATE?: TimeSeriesDuplicatePolicies;
|
||||||
LABELS?: Labels;
|
LABELS?: Labels;
|
||||||
|
IGNORE?: TsIgnoreOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -47,6 +54,8 @@ export default {
|
|||||||
|
|
||||||
pushLabelsArgument(args, options?.LABELS);
|
pushLabelsArgument(args, options?.LABELS);
|
||||||
|
|
||||||
|
pushIgnoreArgument(args, options?.IGNORE);
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => NumberReply
|
transformReply: undefined as unknown as () => NumberReply
|
||||||
|
@@ -48,15 +48,28 @@ describe('TS.ALTER', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => {
|
it('with IGNORE', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
ALTER.transformArguments('key', {
|
||||||
|
IGNORE: {
|
||||||
|
maxTimeDiff: 1,
|
||||||
|
maxValDiff: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.ALTER', 'key', 'IGNORE', '1', '1']
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with RETENTION, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
ALTER.transformArguments('key', {
|
ALTER.transformArguments('key', {
|
||||||
RETENTION: 1,
|
RETENTION: 1,
|
||||||
CHUNK_SIZE: 1,
|
CHUNK_SIZE: 1,
|
||||||
DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
||||||
LABELS: { label: 'value' }
|
LABELS: { label: 'value' },
|
||||||
|
IGNORE: { maxTimeDiff: 1, maxValDiff: 1}
|
||||||
}),
|
}),
|
||||||
['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value']
|
['TS.ALTER', 'key', 'RETENTION', '1', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
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 { TsCreateOptions } from './CREATE';
|
||||||
import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument } from '.';
|
import { pushRetentionArgument, pushChunkSizeArgument, pushDuplicatePolicy, pushLabelsArgument, pushIgnoreArgument } from '.';
|
||||||
|
|
||||||
export type TsAlterOptions = Pick<TsCreateOptions, 'RETENTION' | 'CHUNK_SIZE' | 'DUPLICATE_POLICY' | 'LABELS'>;
|
export type TsAlterOptions = Pick<TsCreateOptions, 'RETENTION' | 'CHUNK_SIZE' | 'DUPLICATE_POLICY' | 'LABELS' | 'IGNORE'>;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
FIRST_KEY_INDEX: 1,
|
FIRST_KEY_INDEX: 1,
|
||||||
@@ -18,6 +18,8 @@ export default {
|
|||||||
|
|
||||||
pushLabelsArgument(args, options?.LABELS);
|
pushLabelsArgument(args, options?.LABELS);
|
||||||
|
|
||||||
|
pushIgnoreArgument(args, options?.IGNORE);
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
||||||
|
@@ -57,16 +57,29 @@ describe('TS.CREATE', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS', () => {
|
it('with IGNORE', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
CREATE.transformArguments('key', {
|
||||||
|
IGNORE: {
|
||||||
|
maxTimeDiff: 1,
|
||||||
|
maxValDiff: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.CREATE', 'key', 'IGNORE', '1', '1']
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
it('with RETENTION, ENCODING, CHUNK_SIZE, DUPLICATE_POLICY, LABELS, IGNORE', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
CREATE.transformArguments('key', {
|
CREATE.transformArguments('key', {
|
||||||
RETENTION: 1,
|
RETENTION: 1,
|
||||||
ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
|
ENCODING: TIME_SERIES_ENCODING.UNCOMPRESSED,
|
||||||
CHUNK_SIZE: 1,
|
CHUNK_SIZE: 1,
|
||||||
DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
DUPLICATE_POLICY: TIME_SERIES_DUPLICATE_POLICIES.BLOCK,
|
||||||
LABELS: { label: 'value' }
|
LABELS: { label: 'value' },
|
||||||
|
IGNORE: { maxTimeDiff: 1, maxValDiff: 1}
|
||||||
}),
|
}),
|
||||||
['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value']
|
['TS.CREATE', 'key', 'RETENTION', '1', 'ENCODING', 'UNCOMPRESSED', 'CHUNK_SIZE', '1', 'DUPLICATE_POLICY', 'BLOCK', 'LABELS', 'label', 'value', 'IGNORE', '1', '1']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -7,8 +7,10 @@ import {
|
|||||||
TimeSeriesDuplicatePolicies,
|
TimeSeriesDuplicatePolicies,
|
||||||
pushDuplicatePolicy,
|
pushDuplicatePolicy,
|
||||||
Labels,
|
Labels,
|
||||||
pushLabelsArgument
|
pushLabelsArgument,
|
||||||
|
pushIgnoreArgument
|
||||||
} from '.';
|
} from '.';
|
||||||
|
import { TsIgnoreOptions } from './ADD';
|
||||||
|
|
||||||
export interface TsCreateOptions {
|
export interface TsCreateOptions {
|
||||||
RETENTION?: number;
|
RETENTION?: number;
|
||||||
@@ -16,6 +18,7 @@ export interface TsCreateOptions {
|
|||||||
CHUNK_SIZE?: number;
|
CHUNK_SIZE?: number;
|
||||||
DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies;
|
DUPLICATE_POLICY?: TimeSeriesDuplicatePolicies;
|
||||||
LABELS?: Labels;
|
LABELS?: Labels;
|
||||||
|
IGNORE?: TsIgnoreOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -34,6 +37,8 @@ export default {
|
|||||||
|
|
||||||
pushLabelsArgument(args, options?.LABELS);
|
pushLabelsArgument(args, options?.LABELS);
|
||||||
|
|
||||||
|
pushIgnoreArgument(args, options?.IGNORE);
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
},
|
},
|
||||||
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
transformReply: undefined as unknown as () => SimpleStringReply<'OK'>
|
||||||
|
@@ -56,6 +56,18 @@ describe('TS.DECRBY', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it ('with IGNORE', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
DECRBY.transformArguments('key', 1, {
|
||||||
|
IGNORE: {
|
||||||
|
maxTimeDiff: 1,
|
||||||
|
maxValDiff: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.DECRBY', 'key', '1', 'IGNORE', '1', '1']
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => {
|
it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
DECRBY.transformArguments('key', 1, {
|
DECRBY.transformArguments('key', 1, {
|
||||||
@@ -63,9 +75,10 @@ describe('TS.DECRBY', () => {
|
|||||||
RETENTION: 1,
|
RETENTION: 1,
|
||||||
UNCOMPRESSED: true,
|
UNCOMPRESSED: true,
|
||||||
CHUNK_SIZE: 2,
|
CHUNK_SIZE: 2,
|
||||||
LABELS: { label: 'value' }
|
LABELS: { label: 'value' },
|
||||||
|
IGNORE: { maxTimeDiff: 1, maxValDiff: 1 }
|
||||||
}),
|
}),
|
||||||
['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value']
|
['TS.DECRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED', 'CHUNK_SIZE', '2', 'LABELS', 'label', 'value', 'IGNORE', '1', '1']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -65,6 +65,18 @@ describe('TS.INCRBY', () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it ('with IGNORE', () => {
|
||||||
|
assert.deepEqual(
|
||||||
|
INCRBY.transformArguments('key', 1, {
|
||||||
|
IGNORE: {
|
||||||
|
maxTimeDiff: 1,
|
||||||
|
maxValDiff: 1
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
['TS.INCRBY', 'key', '1', 'IGNORE', '1', '1']
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => {
|
it('with TIMESTAMP, RETENTION, UNCOMPRESSED, CHUNK_SIZE and LABELS', () => {
|
||||||
assert.deepEqual(
|
assert.deepEqual(
|
||||||
INCRBY.transformArguments('key', 1, {
|
INCRBY.transformArguments('key', 1, {
|
||||||
@@ -72,10 +84,11 @@ describe('TS.INCRBY', () => {
|
|||||||
RETENTION: 1,
|
RETENTION: 1,
|
||||||
UNCOMPRESSED: true,
|
UNCOMPRESSED: true,
|
||||||
CHUNK_SIZE: 1,
|
CHUNK_SIZE: 1,
|
||||||
LABELS: { label: 'value' }
|
LABELS: { label: 'value' },
|
||||||
|
IGNORE: { maxTimeDiff: 1, maxValDiff: 1 }
|
||||||
}),
|
}),
|
||||||
['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED',
|
['TS.INCRBY', 'key', '1', 'TIMESTAMP', '*', 'RETENTION', '1', 'UNCOMPRESSED',
|
||||||
'CHUNK_SIZE', '1', 'LABELS', 'label', 'value']
|
'CHUNK_SIZE', '1', 'LABELS', 'label', 'value', 'IGNORE', '1', '1']
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
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 '.';
|
import { Timestamp, transformTimestampArgument, pushRetentionArgument, pushChunkSizeArgument, Labels, pushLabelsArgument, pushIgnoreArgument } from '.';
|
||||||
|
import { TsIgnoreOptions } from './ADD';
|
||||||
|
|
||||||
export interface TsIncrByOptions {
|
export interface TsIncrByOptions {
|
||||||
TIMESTAMP?: Timestamp;
|
TIMESTAMP?: Timestamp;
|
||||||
@@ -7,6 +8,7 @@ export interface TsIncrByOptions {
|
|||||||
UNCOMPRESSED?: boolean;
|
UNCOMPRESSED?: boolean;
|
||||||
CHUNK_SIZE?: number;
|
CHUNK_SIZE?: number;
|
||||||
LABELS?: Labels;
|
LABELS?: Labels;
|
||||||
|
IGNORE?: TsIgnoreOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transformIncrByArguments(
|
export function transformIncrByArguments(
|
||||||
@@ -35,6 +37,8 @@ export function transformIncrByArguments(
|
|||||||
|
|
||||||
pushLabelsArgument(args, options?.LABELS);
|
pushLabelsArgument(args, options?.LABELS);
|
||||||
|
|
||||||
|
pushIgnoreArgument(args, options?.IGNORE);
|
||||||
|
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import type { BlobStringReply, CommandArguments, DoubleReply, NumberReply, RedisArgument, RedisCommands, TuplesReply, UnwrapReply } 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 ADD, { TsIgnoreOptions } from './ADD';
|
||||||
import ALTER from './ALTER';
|
import ALTER from './ALTER';
|
||||||
import CREATE from './CREATE';
|
import CREATE from './CREATE';
|
||||||
import CREATERULE from './CREATERULE';
|
import CREATERULE from './CREATERULE';
|
||||||
@@ -67,6 +67,12 @@ export default {
|
|||||||
revRange: REVRANGE
|
revRange: REVRANGE
|
||||||
} as const satisfies RedisCommands;
|
} as const satisfies RedisCommands;
|
||||||
|
|
||||||
|
export function pushIgnoreArgument(args: Array<RedisArgument>, ignore?: TsIgnoreOptions) {
|
||||||
|
if (ignore !== undefined) {
|
||||||
|
args.push('IGNORE', ignore.maxTimeDiff.toString(), ignore.maxValDiff.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
|
export function pushRetentionArgument(args: Array<RedisArgument>, retention?: number) {
|
||||||
if (retention !== undefined) {
|
if (retention !== undefined) {
|
||||||
args.push('RETENTION', retention.toString());
|
args.push('RETENTION', retention.toString());
|
||||||
|
Reference in New Issue
Block a user