@@ -91,7 +91,10 @@ void add_shouldInsertSingleMessage(String content, MessageType messageType) {
9191 default -> throw new IllegalArgumentException ("Type not supported: " + messageType );
9292 };
9393
94+ java .time .Instant beforeSave = java .time .Instant .now ();
9495 chatMemory .saveAll (conversationId , List .of (message ));
96+ java .time .Instant afterSave = java .time .Instant .now ();
97+
9598 sleepForSearchable ();
9699 assertThat (chatMemory .findConversationIds ()).isNotEmpty ();
97100 assertThat (chatMemory .findConversationIds ()).contains (conversationId );
@@ -100,6 +103,15 @@ void add_shouldInsertSingleMessage(String content, MessageType messageType) {
100103 assertThat (retrievedMessages ).hasSize (1 );
101104 assertThat (retrievedMessages .get (0 ).getText ()).isEqualTo (content );
102105 assertThat (retrievedMessages .get (0 ).getMessageType ()).isEqualTo (messageType );
106+
107+ // Verify timestamp was automatically added
108+ Object timestampObj = retrievedMessages .get (0 )
109+ .getMetadata ()
110+ .get (ElasticSearchChatMemoryRepository .CONVERSATION_TS );
111+ assertThat (timestampObj ).as ("Timestamp should be automatically added" ).isNotNull ();
112+ assertThat (timestampObj ).isInstanceOf (java .time .Instant .class );
113+ java .time .Instant timestamp = (java .time .Instant ) timestampObj ;
114+ assertThat (timestamp ).isBetween (beforeSave .minusSeconds (1 ), afterSave .plusSeconds (1 ));
103115 });
104116 }
105117
@@ -115,17 +127,21 @@ void shouldSaveAndRetrieveMultipleMessages() {
115127
116128 var conversationId = UUID .randomUUID ().toString ();
117129
130+ // Use 5 messages to verify sequenceNumber preserves order
118131 List <Message > messages = List .of (new SystemMessage ("System message" ), new UserMessage ("User message" ),
119- new AssistantMessage ("Assistant message" ));
132+ new AssistantMessage ("Assistant message" ), new UserMessage ("Second user message" ),
133+ new AssistantMessage ("Second assistant message" ));
120134
135+ java .time .Instant beforeSave = java .time .Instant .now ();
121136 chatMemory .saveAll (conversationId , messages );
137+ java .time .Instant afterSave = java .time .Instant .now ();
122138
123139 sleepForSearchable ();
124140
125141 List <Message > retrievedMessages = chatMemory .findByConversationId (conversationId );
126- assertThat (retrievedMessages ).hasSize (3 );
142+ assertThat (retrievedMessages ).hasSize (5 );
127143
128- // Messages should be in the same order they were saved
144+ // Verify sequenceNumber preserves message order
129145 assertThat (retrievedMessages .get (0 ).getText ()).isEqualTo ("System message" );
130146 assertThat (retrievedMessages .get (0 ).getMessageType ()).isEqualTo (MessageType .SYSTEM );
131147
@@ -134,6 +150,31 @@ void shouldSaveAndRetrieveMultipleMessages() {
134150
135151 assertThat (retrievedMessages .get (2 ).getText ()).isEqualTo ("Assistant message" );
136152 assertThat (retrievedMessages .get (2 ).getMessageType ()).isEqualTo (MessageType .ASSISTANT );
153+
154+ assertThat (retrievedMessages .get (3 ).getText ()).isEqualTo ("Second user message" );
155+ assertThat (retrievedMessages .get (3 ).getMessageType ()).isEqualTo (MessageType .USER );
156+
157+ assertThat (retrievedMessages .get (4 ).getText ()).isEqualTo ("Second assistant message" );
158+ assertThat (retrievedMessages .get (4 ).getMessageType ()).isEqualTo (MessageType .ASSISTANT );
159+
160+ // Verify timestamp consistency: all messages saved together should have the
161+ // same timestamp
162+ java .time .Instant firstTimestamp = null ;
163+ for (Message message : retrievedMessages ) {
164+ Object timestampObj = message .getMetadata ().get (ElasticSearchChatMemoryRepository .CONVERSATION_TS );
165+ assertThat (timestampObj ).isNotNull ();
166+
167+ java .time .Instant timestamp = (java .time .Instant ) timestampObj ;
168+ assertThat (timestamp ).isBetween (beforeSave .minusSeconds (1 ), afterSave .plusSeconds (1 ));
169+
170+ if (firstTimestamp == null ) {
171+ firstTimestamp = timestamp ;
172+ }
173+ else {
174+ // All messages in same saveAll should have identical timestamp
175+ assertThat (timestamp ).isEqualTo (firstTimestamp );
176+ }
177+ }
137178 });
138179 }
139180
@@ -143,18 +184,24 @@ void shouldReplaceExistingMessages() {
143184 var chatMemory = context .getBean (ChatMemoryRepository .class );
144185 var conversationId = UUID .randomUUID ().toString ();
145186
146- // Save initial messages
187+ // Save initial messages (3 messages)
147188 List <Message > initialMessages = List .of (new UserMessage ("Initial user message" ),
148- new AssistantMessage ("Initial assistant message" ));
189+ new AssistantMessage ("Initial assistant message" ), new UserMessage ( "Initial third message" ) );
149190 chatMemory .saveAll (conversationId , initialMessages );
150191
151192 sleepForSearchable ();
152193
153- // Verify initial save
194+ // Verify initial save and capture timestamp
154195 List <Message > retrievedMessages = chatMemory .findByConversationId (conversationId );
155- assertThat (retrievedMessages ).hasSize (2 );
196+ assertThat (retrievedMessages ).hasSize (3 );
197+ java .time .Instant initialTimestamp = (java .time .Instant ) retrievedMessages .get (0 )
198+ .getMetadata ()
199+ .get (ElasticSearchChatMemoryRepository .CONVERSATION_TS );
156200
157- // Replace with new messages
201+ // Wait to ensure timestamp difference
202+ TimeUnit .MILLISECONDS .sleep (100 );
203+
204+ // Replace with new messages (2 messages - verify sequenceNumber restarts)
158205 List <Message > newMessages = List .of (new SystemMessage ("New system message" ),
159206 new UserMessage ("New user message" ));
160207 chatMemory .saveAll (conversationId , newMessages );
@@ -166,6 +213,12 @@ void shouldReplaceExistingMessages() {
166213 assertThat (retrievedMessages ).hasSize (2 );
167214 assertThat (retrievedMessages .get (0 ).getText ()).isEqualTo ("New system message" );
168215 assertThat (retrievedMessages .get (1 ).getText ()).isEqualTo ("New user message" );
216+
217+ // Verify timestamp was updated (should be after initial timestamp)
218+ java .time .Instant updatedTimestamp = (java .time .Instant ) retrievedMessages .get (0 )
219+ .getMetadata ()
220+ .get (ElasticSearchChatMemoryRepository .CONVERSATION_TS );
221+ assertThat (updatedTimestamp ).isAfter (initialTimestamp );
169222 });
170223 }
171224
0 commit comments