Skip to content

feat: add TS.READ command support to the timeseries module - #4170

Merged
petyaslavova merged 6 commits into
masterfrom
ps_add_ts_read_support
Jul 9, 2026
Merged

petyaslavova merged 6 commits into
masterfrom
ps_add_ts_read_support

Conversation

@petyaslavova

@petyaslavova petyaslavova commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Change summary

This pull request adds support for the TS.READ command to the RedisTimeSeries client. TS.READ reads a batch of samples with timestamps at or after a given cursor in ascending order, and optionally blocks until a minimum number of samples qualify — letting callers consume historical and newly-appended samples continuously, in batches, without polling TS.RANGE.

The core change is a new read() method on TimeSeriesCommands in redis/commands/timeseries/commands.py, exposed with sync/async @overload signatures. It accepts key, an inclusive timestamp cursor (a non-negative integer in Unix milliseconds or one of the server-side sentinels -, +, $), and the optional block_milliseconds, block_min_count, and max_count parameters. Two static helpers, _append_block and _append_max_count, build the wire arguments; _append_block enforces the command's all-or-nothing BLOCK group by raising DataError when block_min_count is supplied without block_milliseconds, and defaults min_count to 1 when blocking is requested.

Result parsing is wired up in redis/commands/timeseries/__init__.py: READ_CMD ("TS.READ") is registered to parse_range_unified for both the RESP2 and RESP3 unified callback maps, so the command returns the same [[timestamp, value], ...] sample shape regardless of protocol. An empty list is a successful reply — returned when nothing qualifies or when a blocking call times out with nothing available.

The change is additive and backward-compatible: it introduces a new public method with no changes to existing signatures, return types, or protocol handling. The docstring notes an important operational caveat — a blocking call parks the connection for up to block_milliseconds, so the client's socket_timeout must be configured larger than the block window (or None), and the command must not be retried automatically after an empty or partial reply.

Test coverage

New tests are added in both tests/test_timeseries.py and tests/test_asyncio/test_timeseries.py, keeping sync/async parity. They cover the core read with an inclusive cursor, max_count bounded paging, the + and - sentinels, empty replies (cursor past the newest sample and a missing key), blocking behavior (immediate return when min_count is met, flush of available samples on timeout, and empty reply when nothing is available), and the validation path where block_min_count without block_milliseconds raises DataError.


Note

Low Risk
Additive public API only; blocking semantics mirror other blocking Redis commands and are documented for timeout/retry pitfalls.

Overview
Adds TS.READ to the RedisTimeSeries client via a new read() on TimeSeriesCommands, with sync/async overloads returning ascending [[timestamp, value], ...] batches from an inclusive cursor (ms or - / + / $).

Wire args are built with new _append_block (all-or-nothing BLOCK ms min_count, default min 1; DataError if block_min_count is set without block_milliseconds) and _append_max_count. READ_CMD is registered in the timeseries module init to parse_range_unified so replies match unified range shape across protocols.

Sync and async tests (Redis ≥ 8.9.0) cover paging, sentinels, empty/missing keys, blocking behavior, and the BLOCK validation path. The docstring calls out socket_timeout vs long blocks and avoiding automatic retries after empty/partial blocking replies.

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

@petyaslavova petyaslavova added the feature New feature label Jul 7, 2026
@petyaslavova
petyaslavova merged commit 990c11c into master Jul 9, 2026
730 of 731 checks passed
@petyaslavova
petyaslavova deleted the ps_add_ts_read_support branch July 9, 2026 04:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants