Skip to content

Commit 69d7bd6

Browse files
committed
chat-memory-jdbc:
* set timestamp manually to prevent saving equal timestamps while batch insert * return DESC order into get query (in `JdbcChatMemory`) Signed-off-by: Linar Abzaltdinov <[email protected]>
1 parent 87cbe71 commit 69d7bd6

File tree

3 files changed

+36
-7
lines changed

3 files changed

+36
-7
lines changed

auto-configurations/models/chat/memory/spring-ai-autoconfigure-model-chat-memory-jdbc/src/test/java/org/springframework/ai/model/chat/memory/jdbc/autoconfigure/JdbcChatMemoryPostgresqlAutoConfigurationIT.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,13 @@ void addGetAndClear_shouldAllExecute() {
8787
assertThat(chatMemory.get(conversationId, Integer.MAX_VALUE)).hasSize(1);
8888
assertThat(chatMemory.get(conversationId, Integer.MAX_VALUE)).isEqualTo(List.of(userMessage));
8989

90+
var assistantMessage = new AssistantMessage("Message from the assistant");
91+
92+
chatMemory.add(conversationId, List.of(assistantMessage));
93+
94+
assertThat(chatMemory.get(conversationId)).hasSize(2);
95+
assertThat(chatMemory.get(conversationId)).isEqualTo(List.of(userMessage, assistantMessage));
96+
9097
chatMemory.clear(conversationId);
9198

9299
assertThat(chatMemory.get(conversationId, Integer.MAX_VALUE)).isEmpty();
@@ -142,6 +149,13 @@ void useAutoConfiguredChatMemoryWithJdbc() {
142149
assertThat(chatMemory.get(conversationId)).hasSize(1);
143150
assertThat(chatMemory.get(conversationId)).isEqualTo(List.of(userMessage));
144151

152+
var assistantMessage = new AssistantMessage("Message from the assistant");
153+
154+
chatMemory.add(conversationId, List.of(assistantMessage));
155+
156+
assertThat(chatMemory.get(conversationId)).hasSize(2);
157+
assertThat(chatMemory.get(conversationId)).isEqualTo(List.of(userMessage, assistantMessage));
158+
145159
chatMemory.clear(conversationId);
146160

147161
assertThat(chatMemory.get(conversationId)).isEmpty();

memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemory.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.time.Instant;
2424
import java.util.Collections;
2525
import java.util.List;
26+
import java.util.concurrent.atomic.AtomicLong;
2627

2728
import org.springframework.ai.chat.memory.ChatMemory;
2829
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
@@ -52,7 +53,7 @@ public class JdbcChatMemory implements ChatMemory {
5253
INSERT INTO ai_chat_memory (conversation_id, content, type, "timestamp") VALUES (?, ?, ?, ?)""";
5354

5455
private static final String QUERY_GET = """
55-
SELECT content, type FROM ai_chat_memory WHERE conversation_id = ? ORDER BY "timestamp" LIMIT ?""";
56+
SELECT content, type FROM ai_chat_memory WHERE conversation_id = ? ORDER BY "timestamp" DESC LIMIT ?""";
5657

5758
private static final String QUERY_CLEAR = "DELETE FROM ai_chat_memory WHERE conversation_id = ?";
5859

@@ -83,16 +84,21 @@ public void clear(String conversationId) {
8384
this.jdbcTemplate.update(QUERY_CLEAR, conversationId);
8485
}
8586

86-
private record AddBatchPreparedStatement(String conversationId,
87-
List<Message> messages) implements BatchPreparedStatementSetter {
87+
private record AddBatchPreparedStatement(String conversationId, List<Message> messages,
88+
AtomicLong instantSeq) implements BatchPreparedStatementSetter {
89+
90+
private AddBatchPreparedStatement(String conversationId, List<Message> messages) {
91+
this(conversationId, messages, new AtomicLong(Instant.now().toEpochMilli()));
92+
}
93+
8894
@Override
8995
public void setValues(PreparedStatement ps, int i) throws SQLException {
9096
var message = this.messages.get(i);
9197

9298
ps.setString(1, this.conversationId);
9399
ps.setString(2, message.getText());
94100
ps.setString(3, message.getMessageType().name());
95-
ps.setTimestamp(4, Timestamp.from(Instant.now()));
101+
ps.setTimestamp(4, new Timestamp(instantSeq.getAndIncrement()));
96102
}
97103

98104
@Override

memory/spring-ai-model-chat-memory-jdbc/src/main/java/org/springframework/ai/chat/memory/jdbc/JdbcChatMemoryRepository.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@
2727
import java.sql.PreparedStatement;
2828
import java.sql.ResultSet;
2929
import java.sql.SQLException;
30+
import java.sql.Timestamp;
31+
import java.time.Instant;
3032
import java.util.ArrayList;
3133
import java.util.List;
34+
import java.util.concurrent.atomic.AtomicLong;
3235

3336
/**
3437
* An implementation of {@link ChatMemoryRepository} for JDBC.
@@ -44,7 +47,7 @@ public class JdbcChatMemoryRepository implements ChatMemoryRepository {
4447
""";
4548

4649
private static final String QUERY_ADD = """
47-
INSERT INTO ai_chat_memory (conversation_id, content, type) VALUES (?, ?, ?)
50+
INSERT INTO ai_chat_memory (conversation_id, content, type, "timestamp") VALUES (?, ?, ?, ?)
4851
""";
4952

5053
private static final String QUERY_GET = """
@@ -93,15 +96,21 @@ public void deleteByConversationId(String conversationId) {
9396
this.jdbcTemplate.update(QUERY_CLEAR, conversationId);
9497
}
9598

96-
private record AddBatchPreparedStatement(String conversationId,
97-
List<Message> messages) implements BatchPreparedStatementSetter {
99+
private record AddBatchPreparedStatement(String conversationId, List<Message> messages,
100+
AtomicLong instantSeq) implements BatchPreparedStatementSetter {
101+
102+
private AddBatchPreparedStatement(String conversationId, List<Message> messages) {
103+
this(conversationId, messages, new AtomicLong(Instant.now().toEpochMilli()));
104+
}
105+
98106
@Override
99107
public void setValues(PreparedStatement ps, int i) throws SQLException {
100108
var message = this.messages.get(i);
101109

102110
ps.setString(1, this.conversationId);
103111
ps.setString(2, message.getText());
104112
ps.setString(3, message.getMessageType().name());
113+
ps.setTimestamp(4, new Timestamp(instantSeq.getAndIncrement()));
105114
}
106115

107116
@Override

0 commit comments

Comments
 (0)