Add Redis TimeSeries write commands (2/6) by a-TODO-rov · Pull Request #3968 · redis/lettuce · GitHub
Skip to content

Add Redis TimeSeries write commands (2/6) - #3968

Merged
a-TODO-rov merged 12 commits into
ts/p1-lifecyclefrom
ts/p2-writes
Oct 22, 2026
Merged

a-TODO-rov merged 12 commits into
ts/p1-lifecyclefrom
ts/p2-writes

Conversation

@a-TODO-rov

@a-TODO-rov a-TODO-rov commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds TS.ADD, TS.MADD, TS.INCRBY and TS.DECRBY to every API flavor, including the series options these commands accept: ON_DUPLICATE, IGNORE and LABELS last.

Key Decisions & Assumptions

  • tsAdd without a timestamp sends *, so the server clock sets it. The Java Javadoc warns that tsAdd(key, long) would silently become tsAdd(key, double).
  • TS.MADD answers each sample separately, so a rejected sample (for example a duplicate under policy BLOCK) is a null element and the other samples are still stored. The parsing is done by a new ErrorTolerantIntegerListOutput, following the existing ErrorTolerantBooleanListOutput (BF.MADD). The reactive API returns Value.empty() and Kotlin returns List<Long?>.
  • With the Redis Cluster API, TS.MADD is split into one command per slot, as mget is. The result keeps the caller's order. The split is not atomic across slots, which is documented. Node selection runs the command unchanged on each selected node.

Behavioral / Conceptual Changes

IGNORE only takes effect with the duplicate policy LAST. This is server behavior, documented in the Javadoc and the user guide.

Testing

  • Unit tests: argument encoding, the error-tolerant outputs (including a reply split across two network reads) and slot partitioning.
  • Integration tests: each duplicate policy, IGNORE and MADD partial failure, plus the cluster split with sync, async, reactive and a binary codec.

Notes


Note

Medium Risk
New public API surface and cluster slot-splitting for tsMAdd can leave partial writes if one slot fails; MADD partial-failure parsing is protocol-sensitive but heavily tested.

Overview
Adds Redis TimeSeries write commands across sync, async, reactive, Kotlin coroutines, and cluster APIs: tsAdd (explicit timestamp or server *), tsMAdd, tsIncrBy, and tsDecrBy, with TsAddArgs / TsIncrByArgs for series-creation options, per-call ON_DUPLICATE, IGNORE, and labels.

TS.MADD uses new error-tolerant list outputs so per-sample Redis errors become null (or Value.empty() / List<Long?>) without failing the whole command. On Redis Cluster, multi-slot tsMAdd is split per hash slot via TimeSeriesSlotPartition, results are merged in caller order, and cross-slot execution is documented as non-atomic.

The user guide gains a Writes section (including the tsAdd(key, long) footgun). Integration and unit tests cover encoding, duplicate/IGNORE behavior, cluster splits, and RESP framing.

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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

@a-TODO-rov
a-TODO-rov added this pull request to stack #3973 October 21, 2026 11:50
@a-TODO-rov
a-TODO-rov removed this pull request from stack #3973 October 22, 2026 08:21
@a-TODO-rov
a-TODO-rov added this pull request to stack #3977 October 22, 2026 08:21
a-TODO-rov and others added 12 commits October 22, 2026 11:22
Add the TS.ADD, TS.MADD, TS.INCRBY and TS.DECRBY command types and the
ON_DUPLICATE and TIMESTAMP keywords.
Add the TS.ADD arguments with the per-call ON_DUPLICATE override, and
the TS.INCRBY/TS.DECRBY arguments with TIMESTAMP, on the shared series
options. The base serializer now places TIMESTAMP first and
ON_DUPLICATE after DUPLICATE_POLICY, keeping LABELS last.

Co-authored-by: HwangRock <peter9244@catholic.ac.kr>
TsMAddValue is one TS.MADD sample. of(key, timestamp, value) requires a
non-negative timestamp; of(key, value) sends * so that the server clock
sets the timestamp.

Co-authored-by: HwangRock <peter9244@catholic.ac.kr>
TS.MADD replies with an array that holds an error element for each
rejected sample. ErrorTolerantIntegerListOutput turns those elements
into null and ErrorTolerantIntegerValueListOutput into Value.empty(),
reading the reply to the end; an error reply instead of the array still
fails the command.

Co-authored-by: HwangRock <peter9244@catholic.ac.kr>
Add TS.ADD, TS.MADD, TS.INCRBY and TS.DECRBY to every API flavor. The
TS.ADD overloads without a timestamp send * (server clock); their
Javadoc warns that a long passed as the value compiles silently. TS.MADD
returns null for each rejected sample (Value.empty() on the reactive
API, List<Long?> on Kotlin), so the reactive tsMAdd and the builder
method tsMAddValues are registered as known deviations.

Co-authored-by: HwangRock <peter9244@catholic.ac.kr>
The advanced cluster API sends TS.MADD with keys in several slots as one
command per slot, in parallel, and puts the results back in the caller's
order. Samples are partitioned by position, because one key can appear
several times. A slot whose command fails fails the whole call, as with
MGET. The split is not atomic across slots.
Add the writes section to the TimeSeries user guide: TS.ADD with and
without a timestamp and the long-to-double pitfall, IGNORE (only with
duplicate policy LAST), TS.MADD partial failure and the per-slot split
in Redis Cluster, and TS.INCRBY/TS.DECRBY.
The Java long-to-double warning does not apply in Kotlin, which does
not widen a Long to a Double. Drop it from tsAdd(key, value) and
tsAdd(key, value, args), and name the overloads that set the timestamp
as tsAdd(key, timestamp, value) and tsAdd(key, timestamp, value, args).
The slot split happens in the Redis Cluster API only. Name it in the
tsMAdd documentation of all six flavors, and state in the class
documentation of both node-selection interfaces that tsMAdd runs
unchanged on every selected node, so its keys must hash to slots that
node serves.
@a-TODO-rov
a-TODO-rov merged commit 41ce709 into timeseries Oct 22, 2026
2 checks passed
@a-TODO-rov
a-TODO-rov deleted the ts/p2-writes branch October 22, 2026 08:27
@a-TODO-rov a-TODO-rov mentioned this pull request Oct 22, 2026
4 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant