Skip to content

Commit d602682

Browse files
Simon Prickettleibale
andauthored
Adding a RedisTimeSeries example (#1839)
* Adds the start of a timeseries example. * Exports required TimeSeries items. * Fixed import. * Added TS.INFO example output. * Fixed typo. * Fixed typo. * Exported aggregation enum. * Working time series example. Co-authored-by: Leibale Eidelman <[email protected]>
1 parent b68836c commit d602682

File tree

12 files changed

+139
-12
lines changed

12 files changed

+139
-12
lines changed

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ This folder contains example scripts showing how to use Node Redis in different
1717
| `set-scan.js` | An example script that shows how to use the SSCAN iterator functionality |
1818
| `stream-producer.js` | Adds entries to a [Redis Stream](https://redis.io/topics/streams-intro) using the `XADD` command |
1919
| `stream-consumer.js` | Reads entries from a [Redis Stream](https://redis.io/topics/streams-intro) using the blocking `XREAD` command |
20+
| `time-series.js` | Create, populate and query timeseries data with [Redis Timeseries](https://redistimeseries.io) |
2021
| `topk.js` | Use the [RedisBloom](https://redisbloom.io) TopK to track the most frequently seen items. |
2122

2223
## Contributing

examples/time-series.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Add data to a Redis TimeSeries and query it.
2+
// Requires the RedisTimeSeries module: https://redistimeseries.io/
3+
4+
import { createClient } from 'redis';
5+
import { TimeSeriesDuplicatePolicies, TimeSeriesEncoding, TimeSeriesAggregationType } from '@node-redis/time-series';
6+
7+
async function timeSeries() {
8+
const client = createClient();
9+
10+
await client.connect();
11+
await client.del('mytimeseries');
12+
13+
try {
14+
// Create a timeseries
15+
// https://oss.redis.com/redistimeseries/commands/#tscreate
16+
const created = await client.ts.create('mytimeseries', {
17+
RETENTION: 86400000, // 1 day in milliseconds
18+
ENCODING: TimeSeriesEncoding.UNCOMPRESSED, // No compression
19+
DUPLICATE_POLICY: TimeSeriesDuplicatePolicies.BLOCK // No duplicates
20+
});
21+
22+
if (created === 'OK') {
23+
console.log('Created timeseries.');
24+
} else {
25+
console.log('Error creating timeseries :(');
26+
process.exit(1);
27+
}
28+
29+
let value = Math.floor(Math.random() * 1000) + 1; // Random data point value
30+
let currentTimestamp = 1640995200000; // Jan 1 2022 00:00:00
31+
let num = 0;
32+
33+
while (num < 10000) {
34+
// Add a new value to the timeseries, providing our own timestamp:
35+
// https://oss.redis.com/redistimeseries/commands/#tsadd
36+
await client.ts.add('mytimeseries', currentTimestamp, value);
37+
console.log(`Added timestamp ${currentTimestamp}, value ${value}.`);
38+
39+
num += 1;
40+
value = Math.floor(Math.random() * 1000) + 1; // Get another random value
41+
currentTimestamp += 1000; // Move on one second.
42+
}
43+
44+
// Add multiple values to the timeseries in round trip to the server:
45+
// https://oss.redis.com/redistimeseries/commands/#tsmadd
46+
const response = await client.ts.mAdd([{
47+
key: 'mytimeseries',
48+
timestamp: currentTimestamp + 60000,
49+
value: Math.floor(Math.random() * 1000) + 1
50+
}, {
51+
key: 'mytimeseries',
52+
timestamp: currentTimestamp + 120000,
53+
value: Math.floor(Math.random() * 1000) + 1
54+
}]);
55+
56+
// response = array of timestamps added by TS.MADD command.
57+
if (response.length === 2) {
58+
console.log('Added 2 entries to timeseries with TS.MADD.');
59+
}
60+
61+
// Update timeseries retention with TS.ALTER:
62+
// https://oss.redis.com/redistimeseries/commands/#tsalter
63+
const alterResponse = await client.ts.alter('mytimeseries', {
64+
RETENTION: 0 // Keep the entries forever
65+
});
66+
67+
if (alterResponse === 'OK') {
68+
console.log('Timeseries retention settings altered successfully.');
69+
}
70+
71+
// Query the timeseries with TS.RANGE:
72+
// https://oss.redis.com/redistimeseries/commands/#tsrangetsrevrange
73+
const fromTimestamp = 1640995200000; // Jan 1 2022 00:00:00
74+
const toTimestamp = 1640995260000; // Jan 1 2022 00:01:00
75+
const rangeResponse = await client.ts.range('mytimeseries', fromTimestamp, toTimestamp, {
76+
// Group into 10 second averages.
77+
AGGREGATION: {
78+
type: TimeSeriesAggregationType.AVERAGE,
79+
timeBucket: 10000
80+
}
81+
});
82+
83+
console.log('RANGE RESPONSE:');
84+
// rangeResponse looks like:
85+
// [
86+
// { timestamp: 1640995200000, value: 356.8 },
87+
// { timestamp: 1640995210000, value: 534.8 },
88+
// { timestamp: 1640995220000, value: 481.3 },
89+
// { timestamp: 1640995230000, value: 437 },
90+
// { timestamp: 1640995240000, value: 507.3 },
91+
// { timestamp: 1640995250000, value: 581.2 },
92+
// { timestamp: 1640995260000, value: 600 }
93+
// ]
94+
95+
console.log(rangeResponse);
96+
97+
// Get some information about the state of the timeseries.
98+
// https://oss.redis.com/redistimeseries/commands/#tsinfo
99+
const tsInfo = await client.ts.info('mytimeseries');
100+
101+
// tsInfo looks like this:
102+
// {
103+
// totalSamples: 1440,
104+
// memoryUsage: 28904,
105+
// firstTimestamp: 1641508920000,
106+
// lastTimestamp: 1641595320000,
107+
// retentionTime: 86400000,
108+
// chunkCount: 7,
109+
// chunkSize: 4096,
110+
// chunkType: 'uncompressed',
111+
// duplicatePolicy: 'block',
112+
// labels: [],
113+
// sourceKey: null,
114+
// rules: []
115+
// }
116+
117+
console.log('Timeseries info:');
118+
console.log(tsInfo);
119+
} catch (e) {
120+
console.error(e);
121+
}
122+
123+
await client.quit();
124+
}
125+
126+
timeSeries();

packages/time-series/lib/commands/CREATERULE.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { transformArguments } from './CREATERULE';
66
describe('CREATERULE', () => {
77
it('transformArguments', () => {
88
assert.deepEqual(
9-
transformArguments('source', 'destination', TimeSeriesAggregationType.AVARAGE, 1),
9+
transformArguments('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1),
1010
['TS.CREATERULE', 'source', 'destination', 'AGGREGATION', 'avg', '1']
1111
);
1212
});
@@ -18,7 +18,7 @@ describe('CREATERULE', () => {
1818
]);
1919

2020
assert.equal(
21-
await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVARAGE, 1),
21+
await client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1),
2222
'OK'
2323
);
2424
}, GLOBAL.SERVERS.OPEN);

packages/time-series/lib/commands/DELETERULE.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('DELETERULE', () => {
1515
await Promise.all([
1616
client.ts.create('source'),
1717
client.ts.create('destination'),
18-
client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVARAGE, 1)
18+
client.ts.createRule('source', 'destination', TimeSeriesAggregationType.AVERAGE, 1)
1919
]);
2020

2121
assert.equal(

packages/time-series/lib/commands/MRANGE.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('MRANGE', () => {
1515
COUNT: 1,
1616
ALIGN: '-',
1717
AGGREGATION: {
18-
type: TimeSeriesAggregationType.AVARAGE,
18+
type: TimeSeriesAggregationType.AVERAGE,
1919
timeBucket: 1
2020
},
2121
GROUPBY: {

packages/time-series/lib/commands/MRANGE_WITHLABELS.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('MRANGE_WITHLABELS', () => {
1616
COUNT: 1,
1717
ALIGN: '-',
1818
AGGREGATION: {
19-
type: TimeSeriesAggregationType.AVARAGE,
19+
type: TimeSeriesAggregationType.AVERAGE,
2020
timeBucket: 1
2121
},
2222
GROUPBY: {

packages/time-series/lib/commands/MREVRANGE.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('MREVRANGE', () => {
1515
COUNT: 1,
1616
ALIGN: '-',
1717
AGGREGATION: {
18-
type: TimeSeriesAggregationType.AVARAGE,
18+
type: TimeSeriesAggregationType.AVERAGE,
1919
timeBucket: 1
2020
},
2121
GROUPBY: {

packages/time-series/lib/commands/MREVRANGE_WITHLABELS.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('MREVRANGE_WITHLABELS', () => {
1616
COUNT: 1,
1717
ALIGN: '-',
1818
AGGREGATION: {
19-
type: TimeSeriesAggregationType.AVARAGE,
19+
type: TimeSeriesAggregationType.AVERAGE,
2020
timeBucket: 1
2121
},
2222
GROUPBY: {

packages/time-series/lib/commands/RANGE.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('RANGE', () => {
1515
COUNT: 1,
1616
ALIGN: '-',
1717
AGGREGATION: {
18-
type: TimeSeriesAggregationType.AVARAGE,
18+
type: TimeSeriesAggregationType.AVERAGE,
1919
timeBucket: 1
2020
}
2121
}),

packages/time-series/lib/commands/REVRANGE.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('REVRANGE', () => {
5555
assert.deepEqual(
5656
transformArguments('key', '-', '+', {
5757
AGGREGATION: {
58-
type: TimeSeriesAggregationType.AVARAGE,
58+
type: TimeSeriesAggregationType.AVERAGE,
5959
timeBucket: 1
6060
}
6161
}),
@@ -74,7 +74,7 @@ describe('REVRANGE', () => {
7474
COUNT: 1,
7575
ALIGN: '-',
7676
AGGREGATION: {
77-
type: TimeSeriesAggregationType.AVARAGE,
77+
type: TimeSeriesAggregationType.AVERAGE,
7878
timeBucket: 1
7979
}
8080
}),

0 commit comments

Comments
 (0)