Skip to content

[Redis 8.10] Add EXCLUDEEMPTY option to TS.MRANGE / TS.MREVRANGE - #4641

Merged
atakavci merged 8 commits into
redis:masterfrom
atakavci:ali8.10/excludeEmpty
Jul 27, 2026
Merged

atakavci merged 8 commits into
redis:masterfrom
atakavci:ali8.10/excludeEmpty

Conversation

@atakavci

@atakavci atakavci commented Jul 23, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds support for the RedisTimeSeries EXCLUDEEMPTY flag to TSMRangeParams via a new
excludeEmpty() builder method. When set, matching series that report no samples for the
queried range are omitted from the TS.MRANGE / TS.MREVRANGE reply instead of being
returned with an empty samples array.

Key Decisions & Assumptions

  • The flag is emitted once, with the range options and immediately before FILTER, so it
    composes with existing options (WITHLABELS, AGGREGATION, etc.). The response parser is
    unchanged β€” an empty reply simply carries fewer (or zero) series.
  • EXCLUDEEMPTY cannot be combined with GROUPBY. The typed helper rejects this
    combination locally with an IllegalArgumentException before sending a command; a raw
    request that combines them is still sent unchanged and left for the server to reject.
  • Requires server-side support (RedisTimeSeries, Redis 8.9.241+); annotated @since 8.0.

Behavioral / Conceptual Changes

  • excludeEmpty() now emits the EXCLUDEEMPTY keyword; without it, behavior is unchanged.
  • equals/hashCode on TSMRangeParams now account for the new flag, so two params
    differing only by excludeEmpty are no longer considered equal.

Testing

Unit tests cover flag emission and ordering (once, before FILTER), composition with other
range options, absence when unset, equality/hashCode distinction, and local rejection of the
EXCLUDEEMPTY + GROUPBY combination. Integration tests verify that empty series are omitted
from TS.MRANGE and TS.MREVRANGE (order preserved), composition with AGGREGATION, an
all-empty result yielding an empty top-level reply, and that a raw GROUPBY combination
propagates the server error.


Note

Low Risk
Additive API and command encoding for an optional flag; behavior is unchanged unless excludeEmpty() is used, with a clear client-side guard against invalid GROUPBY pairing.

Overview
Adds RedisTimeSeries EXCLUDEEMPTY support for TS.MRANGE / TS.MREVRANGE via a new excludeEmpty() builder on TSMRangeParams, which emits the EXCLUDEEMPTY keyword once (before FILTER) so matching series with no samples in the queried range are omitted instead of returned with empty sample arrays.

EXCLUDEEMPTY + GROUPBY is rejected in addParams with IllegalArgumentException; equals/hashCode now include the flag. TimeSeriesProtocol gains the EXCLUDEEMPTY keyword.

Tests add wire-format and validation coverage, integration scenarios (including aggregation and raw server errors), a V8_10_0_RC2 version constant, TestKeyRegistry.name() for unique label filters, and per-test key cleanup in UnifiedJedisCommandsTestBase.

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

@atakavci
atakavci requested a review from ggivo July 23, 2026 14:15
@atakavci atakavci self-assigned this Jul 23, 2026

@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: cff0fed44e

ℹ️ 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".

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 RedisTimeSeries EXCLUDEEMPTY support to Jedis’ TimeSeries multi-range query parameter builder (TSMRangeParams) so callers can omit matching series that have no samples in the requested range for TS.MRANGE / TS.MREVRANGE. This is implemented as an additive, opt-in flag that only affects command argument encoding and is validated against incompatible options.

Changes:

  • Add TSMRangeParams.excludeEmpty() to emit the EXCLUDEEMPTY keyword immediately before FILTER, and include the flag in equals/hashCode.
  • Add local validation to reject EXCLUDEEMPTY combined with GROUPBY in the typed helper API.
  • Add unit and integration tests covering encoding/order, compatibility with other options, equality semantics, and server behavior (including raw command error propagation).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
src/main/java/redis/clients/jedis/timeseries/TSMRangeParams.java Adds excludeEmpty flag, emits EXCLUDEEMPTY before FILTER, validates against GROUPBY, updates equality/hash.
src/main/java/redis/clients/jedis/timeseries/TimeSeriesProtocol.java Adds EXCLUDEEMPTY to TimeSeriesKeyword enum for raw argument encoding.
src/test/java/redis/clients/jedis/timeseries/TSMRangeParamsTest.java Unit tests for argument emission/ordering, absence when unset, composition, equality, and local rejection with GROUPBY.
src/test/java/redis/clients/jedis/commands/unified/timeseries/TimeSeriesCommandsTestBase.java Integration tests verifying TS.MRANGE/TS.MREVRANGE behavior with EXCLUDEEMPTY, including aggregation and raw-command server error propagation.

πŸ’‘ Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@ggivo

ggivo commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Thanks, the implementation and test coverage look good. I've opened atakavci#13 against this PR's branch with test-only improvements: the new integration tests adopt the TestKeyRegistry pattern from #4644 (test-unique series keys and label filter instead of s/t/u and sensor=1 on the shared endpoints), the setup helper returns an explicit ExcludeEmptyFixture instead of mutating fields, and the 8.9.241 gate is extracted into a named RedisVersion constant. Since the changes are a bit involved for review suggestions, merging that PR into your branch (or cherry-picking from it) is probably the easiest way to pick them up.

ggivo and others added 5 commits July 27, 2026 13:57
Expose a per-test TestKeyRegistry from UnifiedJedisCommandsTestBase so
subclasses can generate unique, auto-cleaned keys on the shared test
endpoints. Registered keys are deleted after each test; tests that
register nothing are unaffected.

The new EXCLUDEEMPTY tests adopt it: series keys and the sensor label
value are test-unique, so MRANGE label filters cannot match series
leaked by other suites.
8.10.0 RC2 reports redis_version 8.9.241; name the constant after the
release (V8_10_0_RC2) so version-gated tests read as intent rather
than a magic internal build number.
Replace the mutable s/t/u/sensorFilter fields set by a setup helper
with an immutable ExcludeEmptyFixture returned to each test, so the
values' origin is visible at the call site and the sample layout is
documented once, next to the names assertions use.
Label values, group and consumer names need test-unique values but are
not Redis keys, so registering them for cleanup pollutes the registry
with phantom DELs. name() applies the same expansion as key() without
registering; the EXCLUDEEMPTY sensor label uses it.

@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

@atakavci
atakavci merged commit d4a4f57 into redis:master Jul 27, 2026
14 checks passed
@ggivo ggivo added this to the 8.0.0 milestone Jul 28, 2026
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