Visitar URL original
[Redis 8.10] Support TS.NRANGE and TS.NREVRANGE time series commands by atakavci · Pull Request #4650 · redis/jedis · GitHub
Skip to content

[Redis 8.10] Support TS.NRANGE and TS.NREVRANGE time series commands - #4650

Merged
atakavci merged 14 commits into
redis:masterfrom
atakavci:ali8.10/ts.nrange
Jul 28, 2026
Merged

atakavci merged 14 commits into
redis:masterfrom
atakavci:ali8.10/ts.nrange

Conversation

@atakavci

@atakavci atakavci commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds client support for the multi-key pivot time series commands TS.NRANGE and TS.NREVRANGE. These query an explicit, ordered list of keys over a timestamp range and return a timestamp-major ("pivoted") reply — one row per distinct timestamp, with one value column per key (or per aggregator). The commands are wired through the full command matrix (CommandObjects, UnifiedJedis, PipeliningBase, and the RedisTimeSeries command/pipeline interfaces) and are marked @Experimental.

Key Decisions & Assumptions

  • Keys are passed to the command methods, not carried in params. The new TSNRangeParams holds only fromTimestamp/toTimestamp plus optional args (LATEST, FILTER_BY_TS, FILTER_BY_VALUE, COUNT, and the aggregation clause).
  • Aggregation is per-key: exactly one AGGREGATION token is emitted per key. Convenience overloads accept a single aggregator (single-key only), one aggregator per key, or multiple comma-joined aggregators per key. Matching the token count to numkeys is enforced by the server, not the client.
  • Key order and duplicate keys are significant and preserved; treated as a single-shard, key-routed command (all keys must share a hash slot in cluster mode).
  • Reuses existing TSElement/MultiValueTSElement types and AggregationType.joinRaw.

Behavioral / Conceptual Changes

  • A missing sample or missing aggregation bucket for a key at a given row is surfaced as NaN, indistinguishable from a stored/aggregated NaN.
  • Rows are returned in server order: increasing timestamps for TS.NRANGE, decreasing for TS.NREVRANGE. A new TIMESERIES_PIVOT_ELEMENT_LIST builder parses the pivoted reply for both RESP2 and RESP3, yielding a single-value TSElement for one column or a MultiValueTSElement for several.

Testing

Adds unit coverage for wire-argument construction and TSNRangeParams (option ordering, equals/hashCode, aggregation validation) across CommandObjects, UnifiedJedis, and pipeline surfaces, plus an integration test base exercising the commands against a live server.

Notes

  • New public API is annotated @since 8.0 and @Experimental; signatures may change.
  • The pom.xml change only adds TSNRangeParams.java to the formatter include list — no new dependency.

Note

Low Risk
Additive public API and read-only commands with validation and tests; no changes to auth, persistence, or existing command behavior.

Overview
Adds client support for TS.NRANGE and TS.NREVRANGE, which query an explicit ordered key list over a time range and return timestamp-major pivot rows (one value column per key, NaN for missing cells).

New TSNRangeParams carries range bounds and optional flags (LATEST, filters, COUNT, per-key aggregation with client-side validation that spec count matches numkeys). Keys stay on the command methods; empty key lists are rejected before send.

Commands are wired through CommandObjects, UnifiedJedis, PipeliningBase, and the time-series command interfaces. A dedicated TIMESERIES_PIVOT_ELEMENT_LIST builder maps pivoted replies to TSElement / MultiValueTSElement. DefaultCacheable treats both commands as cacheable reads.

Coverage includes TSNRangeParamsTest, integration tests (gated on command availability), mocked unified/pipeline tests, and test harness cleanup via TestKeyRegistry where needed.

Reviewed by Cursor Bugbot for commit dbdeb54. Bugbot is set up for automated code reviews on this repo. Configure here.

@atakavci
atakavci requested review from Copilot and ggivo July 27, 2026 06:08
@atakavci atakavci self-assigned this Jul 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds experimental Jedis client support for Redis TimeSeries multi-key pivot commands TS.NRANGE and TS.NREVRANGE, wiring them through the standard Jedis command matrix and adding builders/tests to validate argument construction and pivoted reply parsing.

Changes:

  • Introduces TSNRangeParams to model optional args (range, filters, COUNT, per-key aggregation tokens) for TS.NRANGE / TS.NREVRANGE.
  • Adds new command-object methods and exposes new APIs on UnifiedJedis and PipeliningBase plus the TimeSeries command interfaces.
  • Adds pivoted-reply parsing via TimeSeriesBuilderFactory.TIMESERIES_PIVOT_ELEMENT_LIST and broad unit/integration coverage.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/main/java/redis/clients/jedis/timeseries/TSNRangeParams.java New params type for TS.NRANGE / TS.NREVRANGE option encoding and wire ordering.
src/main/java/redis/clients/jedis/timeseries/TimeSeriesProtocol.java Adds NRANGE / NREVRANGE protocol command constants.
src/main/java/redis/clients/jedis/timeseries/TimeSeriesBuilderFactory.java Adds builder to parse timestamp-pivoted responses into TSElement / MultiValueTSElement.
src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesCommands.java Public experimental APIs for tsNRange / tsNRevRange (with/without params).
src/main/java/redis/clients/jedis/timeseries/RedisTimeSeriesPipelineCommands.java Pipeline API additions mirroring the new TimeSeries commands.
src/main/java/redis/clients/jedis/CommandObjects.java Adds command constructors for TS.NRANGE / TS.NREVRANGE using the new builder.
src/main/java/redis/clients/jedis/UnifiedJedis.java Wires new commands through unified client execution.
src/main/java/redis/clients/jedis/PipeliningBase.java Wires new commands through pipeline append/execution.
src/test/java/redis/clients/jedis/timeseries/TSNRangeParamsTest.java Unit tests for wire-argument construction, validation, and equals/hashCode behavior.
src/test/java/redis/clients/jedis/mocked/unified/UnifiedJedisTimeSeriesCommandsTest.java Mocked unified-client delegation tests for new APIs.
src/test/java/redis/clients/jedis/mocked/pipeline/PipeliningBaseTimeSeriesCommandsTest.java Mocked pipeline delegation tests for new APIs.
src/test/java/redis/clients/jedis/commands/unified/timeseries/TimeSeriesCommandsTestBase.java Integration tests exercising pivot semantics, ordering, NaN gaps, and server-side aggregator arity rejection.
src/test/java/redis/clients/jedis/commands/commandobjects/CommandObjectsTimeSeriesCommandsTest.java CommandObjects integration tests for NRANGE/NREVRANGE including aggregation and duplicate-key behavior.
pom.xml Adds TSNRangeParams.java to formatter include list.
Comments suppressed due to low confidence (2)

src/main/java/redis/clients/jedis/timeseries/TSNRangeParams.java:142

  • This Javadoc says each aggregator is emitted as its own AGGREGATION token, but addParams emits AGGREGATION once and then appends one aggregator token per key. Please adjust the wording to match the actual wire format.
   * Applies exactly one aggregator per key, in key order. The number of aggregators must equal the
   * number of keys sent to the command (the server rejects a mismatch). On the wire each aggregator
   * is emitted as its own {@code AGGREGATION} token.
   * @param aggregators ordered, non-empty list holding one aggregator per key

src/main/java/redis/clients/jedis/timeseries/TSNRangeParams.java:250

  • The addParams Javadoc claims one AGGREGATION token is emitted per key, but the implementation emits AGGREGATION once and then emits one aggregator token per key. This should be corrected to avoid confusion.
   * ({@code [ALIGN align] AGGREGATION agg [agg ...]
   * bucketDuration [BUCKETTIMESTAMP bt] [EMPTY]}). One {@code AGGREGATION} token is emitted per
   * key.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ae0e82f49

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b3a10e23e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 26553e47dc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

* per aggregator when multiple aggregators are requested). Missing cells arrive as {@code NaN}.
* The same builder serves RESP2 and RESP3; server-returned row order is preserved.
*/
public static final Builder<List<TSElement>> TIMESERIES_PIVOT_ELEMENT_LIST = new Builder<List<TSElement>>() {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Annotate the public pivot builder with @since

Add an @since 8.0 tag to this newly exposed public builder constant so generated API documentation records when callers can rely on it; the repository requires every new public API to carry that annotation.

AGENTS.md reference: AGENTS.md:L26-L30

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ea8e2c7cd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


private boolean empty;

public TSNRangeParams(long fromTimestamp, long toTimestamp) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Annotate the new parameter members with @SInCE

The class-level @since documents only TSNRangeParams itself; the public constructors, factory methods, and fluent setters beginning here are all newly exposed API members without their own tags, so their generated API entries omit the version in which callers can use them. Add @since 8.0 to each new public member.

AGENTS.md reference: AGENTS.md:L26-L30

Useful? React with 👍 / 👎.

@ggivo ggivo left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM in general

Posted some minor questions; wondering why assertions are using delta?

assertEquals(Arrays.asList(1000L, 2000L, 3000L), timestamps);

assertEquals(2, rows.get(0).getValues().size());
assertEquals(10.0, rows.get(0).getValues().get(0), 0.001);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for using delta/closeto (0.001) in most asserts?
I

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the case, i guess, AI takes measures against rounding errors with double operations, which is right approach most of the time, though there is no double operations this time.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say it make sense for aggreagated values, but for single values I think test should assert actual value directly

@ggivo ggivo added this to the 8.0.0 milestone Jul 28, 2026
@atakavci
atakavci merged commit bc93457 into redis:master Jul 28, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants