spring-projects / spring-projects/spring-ai
RedisChatMemoryRepository.saveAll clears existing messages before preparing replacements
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 9.5k
- Forks
- 2.9k
- Avg merge
- 1d 7h
- Merged PRs (30d)
- 6
Description
Problem
On current main (c988e72ab7282bcc352b2155e8cb27ff4b5e0fda), RedisChatMemoryRepository.saveAll() calls clear(conversationId) before add(conversationId, messages). The replacement list is therefore validated, read, and serialized only after the existing Redis documents have been deleted.
A deterministic reproduction is:
- Save and read back two messages for a conversation.
- Call
saveAll()with one valid replacement followed by aMessagewhosegetMessageType()returnsUSERand whosegetText()throws. - Read the conversation again.
Using Java 17, Maven 3.9.9, rootless Podman 6.0.2, and redis/redis-stack:latest, the exception is propagated, but the original messages are gone and the first replacement message is visible:
Expecting actual:
["Replacement message"]
to contain exactly (and in same order):
["First message", "Second message"]
but some elements were not found:
["First message", "Second message"]
and others were not expected:
["Replacement message"]
The regression test reports one failure, zero errors, and zero skips against the unchanged implementation. The simpler saveAll(conversationId, null) path also clears the conversation before add() rejects the null list.
Expected behavior
Input validation, message-field extraction, and JSON serialization for every replacement message should succeed before the existing conversation is cleared. If that client-side preparation fails, saveAll() should propagate the failure and leave the existing messages unchanged. An empty replacement list should continue to clear the conversation.
Proposed scope
Prepare final Redis keys and JSON payloads for the complete replacement first, then clear the conversation and write those prepared payloads. The existing timestamp-reservation, pipelined writes, and TTL behavior can be retained.
This is deliberately narrower than full replacement atomicity. It does not provide rollback for Redis command or connection failures after destructive Redis operations begin, and it does not claim linearizability for concurrent operations or RediSearch visibility.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at RedisChatMemoryRepository.saveAll() and reproduce the failure with the stated Java, Maven, and Redis setup. Check the regression test described in the issue and verify that preparation failures leave existing messages unchanged, while an empty replacement still clears the conversation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java, redis
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100