Skip to content

Commit 751b95f

Browse files
author
alessandro
committed
Implement support for REVRANGE and MREVRANGE and for WITHLABELS
1 parent 9af07c2 commit 751b95f

File tree

9 files changed

+254
-99
lines changed

9 files changed

+254
-99
lines changed

src/SampleWithLabels.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Palicao\PhpRedisTimeSeries;
5+
6+
use DateTimeInterface;
7+
8+
/** @psalm-immutable */
9+
class SampleWithLabels extends Sample
10+
{
11+
/** @var Label[] */
12+
private $labels;
13+
14+
/**
15+
* SampleWithLabels constructor.
16+
* @param string $key
17+
* @param float $value
18+
* @param DateTimeInterface|null $dateTime
19+
* @param Label[] $labels
20+
*/
21+
public function __construct(string $key, float $value, ?DateTimeInterface $dateTime = null, array $labels = [])
22+
{
23+
parent::__construct($key, $value, $dateTime);
24+
$this->labels = $labels;
25+
}
26+
27+
/**
28+
* @param string $key
29+
* @param float $value
30+
* @param int $timestamp
31+
* @param Label[] $labels
32+
* @return SampleWithLabels
33+
*/
34+
public static function createFromTimestampAndLabels(
35+
string $key,
36+
float $value,
37+
int $timestamp,
38+
array $labels
39+
): SampleWithLabels
40+
{
41+
return new self($key, $value, DateTimeUtils::dateTimeFromTimestampWithMs($timestamp), $labels);
42+
}
43+
44+
/**
45+
* @return Label[]
46+
*/
47+
public function getLabels(): array
48+
{
49+
return $this->labels;
50+
}
51+
}

src/TimeSeries.php

Lines changed: 94 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
use Palicao\PhpRedisTimeSeries\Exception\RedisClientException;
99
use RedisException;
1010

11-
class TimeSeries
11+
final class TimeSeries
1212
{
1313
/** @var RedisClientInterface */
1414
private $redis;
@@ -100,11 +100,16 @@ public function addMany(array $samples): array
100100
$params[] = $sampleParam;
101101
}
102102
}
103+
/** @var int[] $timestamps */
103104
$timestamps = $this->redis->executeCommand($params);
104105
$count = count($timestamps);
105106
$results = [];
106107
for ($i = 0; $i < $count; $i++) {
107-
$results[] = Sample::createFromTimestamp($samples[$i]->getKey(), $samples[$i]->getValue(), $timestamps[$i]);
108+
$results[] = Sample::createFromTimestamp(
109+
$samples[$i]->getKey(),
110+
$samples[$i]->getValue(),
111+
$timestamps[$i]
112+
);
108113
}
109114
return $results;
110115
}
@@ -157,10 +162,10 @@ private function incrementOrDecrementBy(
157162
array $labels = []
158163
): void
159164
{
160-
$params = [$op, $sample->getKey(), $sample->getValue()];
165+
$params = [$op, $sample->getKey(), (string)$sample->getValue()];
161166
if ($resetMs !== null) {
162167
$params[] = 'RESET';
163-
$params[] = $resetMs;
168+
$params[] = (string)$resetMs;
164169
}
165170
if ($sample->getDateTime() !== null) {
166171
$params[] = 'TIMESTAMP';
@@ -214,6 +219,7 @@ public function deleteRule(string $sourceKey, string $destKey): void
214219
* @param DateTimeInterface|null $to
215220
* @param int|null $count
216221
* @param AggregationRule|null $rule
222+
* @param bool $reverse
217223
* @return Sample[]
218224
* @throws RedisClientException
219225
* @throws RedisException
@@ -223,16 +229,18 @@ public function range(
223229
?DateTimeInterface $from = null,
224230
?DateTimeInterface $to = null,
225231
?int $count = null,
226-
?AggregationRule $rule = null
232+
?AggregationRule $rule = null,
233+
bool $reverse = false
227234
): array
228235
{
229-
$fromTs = $from ? DateTimeUtils::timestampWithMsFromDateTime($from) : '-';
230-
$toTs = $to ? DateTimeUtils::timestampWithMsFromDateTime($to) : '+';
236+
$fromTs = $from ? (string)DateTimeUtils::timestampWithMsFromDateTime($from) : '-';
237+
$toTs = $to ? (string)DateTimeUtils::timestampWithMsFromDateTime($to) : '+';
231238

232-
$params = ['TS.RANGE', $key, $fromTs, $toTs];
239+
$command = $reverse ? 'TS.REVRANGE' : 'TS.RANGE';
240+
$params = [$command, $key, $fromTs, $toTs];
233241
if ($count !== null) {
234242
$params[] = 'COUNT';
235-
$params[] = $count;
243+
$params[] = (string)$count;
236244
}
237245

238246
$rawResults = $this->redis->executeCommand(array_merge($params, $this->getAggregationParams($rule)));
@@ -251,6 +259,7 @@ public function range(
251259
* @param DateTimeInterface|null $to
252260
* @param int|null $count
253261
* @param AggregationRule|null $rule
262+
* @param bool $reverse
254263
* @return Sample[]
255264
* @throws RedisClientException
256265
* @throws RedisException
@@ -260,10 +269,11 @@ public function multiRange(
260269
?DateTimeInterface $from = null,
261270
?DateTimeInterface $to = null,
262271
?int $count = null,
263-
?AggregationRule $rule = null
272+
?AggregationRule $rule = null,
273+
bool $reverse = false
264274
): array
265275
{
266-
$results = $this->multiRangeRaw($filter, $from, $to, $count, $rule);
276+
$results = $this->multiRangeRaw($filter, $from, $to, $count, $rule, $reverse);
267277

268278
$samples = [];
269279
foreach ($results as $groupByKey) {
@@ -281,33 +291,82 @@ public function multiRange(
281291
* @param DateTimeInterface|null $to
282292
* @param int|null $count
283293
* @param AggregationRule|null $rule
284-
* @return array The row result from Redis (including labels)
294+
* @param bool $reverse
295+
* @return SampleWithLabels[]
285296
* @throws RedisClientException
286297
* @throws RedisException
287298
*/
288-
public function multiRangeRaw(
299+
public function multiRangeWithLabels(
289300
Filter $filter,
290301
?DateTimeInterface $from = null,
291302
?DateTimeInterface $to = null,
292303
?int $count = null,
293-
?AggregationRule $rule = null
304+
?AggregationRule $rule = null,
305+
bool $reverse = false
294306
): array
295307
{
296-
$fromTs = $from ? DateTimeUtils::timestampWithMsFromDateTime($from) : '-';
297-
$toTs = $to ? DateTimeUtils::timestampWithMsFromDateTime($to) : '+';
308+
$results = $this->multiRangeRaw($filter, $from, $to, $count, $rule, $reverse, true);
309+
310+
$samples = [];
311+
foreach ($results as $groupByKey) {
312+
$key = $groupByKey[0];
313+
$labels = [];
314+
foreach ($groupByKey[1] as $label) {
315+
$labels[] = new Label($label[0], $label[1]);
316+
}
317+
foreach ($groupByKey[2] as $result) {
318+
$samples[] = SampleWithLabels::createFromTimestampAndLabels(
319+
$key,
320+
(float)$result[1],
321+
$result[0],
322+
$labels
323+
);
324+
}
325+
}
326+
return $samples;
327+
}
328+
329+
/**
330+
* @param Filter $filter
331+
* @param DateTimeInterface|null $from
332+
* @param DateTimeInterface|null $to
333+
* @param int|null $count
334+
* @param AggregationRule|null $rule
335+
* @param bool $reverse
336+
* @param bool $withLabels
337+
* @return array
338+
* @throws RedisException
339+
*/
340+
private function multiRangeRaw(
341+
Filter $filter,
342+
?DateTimeInterface $from = null,
343+
?DateTimeInterface $to = null,
344+
?int $count = null,
345+
?AggregationRule $rule = null,
346+
bool $reverse = false,
347+
bool $withLabels = false
348+
): array
349+
{
350+
$fromTs = $from ? (string)DateTimeUtils::timestampWithMsFromDateTime($from) : '-';
351+
$toTs = $to ? (string)DateTimeUtils::timestampWithMsFromDateTime($to) : '+';
352+
353+
$command = $reverse ? 'TS.MREVRANGE' : 'TS.MRANGE';
354+
$params = [$command, $fromTs, $toTs];
298355

299-
$params = ['TS.MRANGE', $fromTs, $toTs];
300356
if ($count !== null) {
301357
$params[] = 'COUNT';
302-
$params[] = $count;
358+
$params[] = (string)$count;
303359
}
304360

305-
return $this->redis->executeCommand(array_merge(
306-
$params,
307-
$this->getAggregationParams($rule),
308-
['FILTER'],
309-
$filter->toRedisParams()
310-
));
361+
$params = array_merge($params, $this->getAggregationParams($rule));
362+
363+
if ($withLabels) {
364+
$params[] = 'WITHLABELS';
365+
}
366+
367+
$params = array_merge($params, ['FILTER'], $filter->toRedisParams());
368+
369+
return $this->redis->executeCommand($params);
311370
}
312371

313372
/**
@@ -385,17 +444,21 @@ public function getKeysByFilter(Filter $filter): array
385444
);
386445
}
387446

447+
/**
448+
* @param int|null $retentionMs
449+
* @return string[]
450+
*/
388451
private function getRetentionParams(?int $retentionMs = null): array
389452
{
390453
if ($retentionMs === null) {
391454
return [];
392455
}
393-
return ['RETENTION', $retentionMs];
456+
return ['RETENTION', (string)$retentionMs];
394457
}
395458

396459
/**
397460
* @param Label ...$labels
398-
* @return array
461+
* @return string[]
399462
*/
400463
private function getLabelsParams(Label ...$labels): array
401464
{
@@ -413,11 +476,15 @@ private function getLabelsParams(Label ...$labels): array
413476
return $params;
414477
}
415478

479+
/**
480+
* @param AggregationRule|null $rule
481+
* @return string[]
482+
*/
416483
private function getAggregationParams(?AggregationRule $rule = null): array
417484
{
418485
if ($rule === null) {
419486
return [];
420487
}
421-
return ['AGGREGATION', $rule->getType(), $rule->getTimeBucketMs()];
488+
return ['AGGREGATION', $rule->getType(), (string)$rule->getTimeBucketMs()];
422489
}
423490
}

0 commit comments

Comments
 (0)