Skip to content

Xadd XAddArgs MAXLEN and MINID exact trimming not allowed #3682

@jtorkkel

Description

@jtorkkel

Expected Behavior

It is not possible to give command containing exact trimming like

xadd uid-stream minid = 1768925632276-4 * key value

Current Behavior

go-redis command rejected by redis

	minId := strconv.FormatInt(int64(time.Now().UnixMilli()-60_000), 10) + "-0"
	args = redis2.XAddArgs{
		Stream:     stream,
		NoMkStream: false,
		MaxLen:     0,
		MinID:      minId,
		Approx:     true, // false not working, bug in go-redis v9 as "=" is not set when true
		Limit:      1000, // trim count
		//Mode:       "MAXLEN~",
		ID:     "",
		Values: m,
	}
s, err := Conn.XAdd(r.Context(), &args).Result()

Possible Solution

Trimming should use either ~ or = characters. go-redis only set "~" when "Approx" is true, but go-redis does not set "=" when Approx is false. go-redis should set "=" on lines MAXLEN or
MINID

	switch {
	case a.MaxLen > 0:
		if a.Approx {
			args = append(args, "maxlen", "~", a.MaxLen)
		} else {
			args = append(args, "maxlen", a.MaxLen) // "=" missing
		}
	case a.MinID != "":
		if a.Approx {
			args = append(args, "minid", "~", a.MinID)
		} else {
			args = append(args, "minid", a.MinID) // "=" missing
		}
	}
	if a.Limit > 0 {
		args = append(args, "limit", a.Limit)
	}

	if a.Mode != "" {
		args = append(args, a.Mode)
	}

	if a.ID != "" {
		args = append(args, a.ID)
	} else {
		args = append(args, "*")
	}
	args = appendArg(args, a.Values)

	cmd := NewStringCmd(ctx, args...)
	_ = c(ctx, cmd)
	

According redis doc.

XADD key [NOMKSTREAM] [KEEPREF | DELREF | ACKED] [<MAXLEN | MINID> [= | ~] threshold
[LIMIT count]] <* | id> field value [field value ...]

MAXLEN | MINID [= | ~] threshold [LIMIT count]>
Trims the stream to maintain a specific size or remove old entries:

MAXLEN | MINID
The trimming strategy:

MAXLEN: Evicts entries as long as the stream's length exceeds the specified threshold
MINID: Evicts entries with IDs lower than the specified threshold (available since Redis 6.2.0)
= | ~
The trimming operator:

=: Exact trimming (default) - trims to the exact threshold
~: Approximate trimming - more efficient, may leave slightly more entries than the threshold

Possible Solution

See above

Steps to Reproduce

go-redis command rejected by redis

	minId := strconv.FormatInt(int64(time.Now().UnixMilli()-60_000), 10) + "-0"
	args = redis2.XAddArgs{
		Stream:     stream,
		NoMkStream: false,
		MaxLen:     0,
		MinID:      minId,
		Approx:     true, // false not working, bug in go-redis v9 as "=" is not set when true
		Limit:      1000, // trim count
		//Mode:       "MAXLEN~",
		ID:     "",
		Values: m,
	}
s, err := Conn.XAdd(r.Context(), &args).Result()

Setting Approx=true works as "~" set.

I failed to understand what is "Mode".

Context (Environment)

go-redis 9.17.2
Windows 11
redis 8.4 running in Docker Desktop

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions