Skip to content

Commit 2fcff3c

Browse files
committed
Extract timestamp as double for InMemorySessionService events
InMemorySessionService sets a Session's last modified time based on when the last appended event's timestamp. The timestamp in an event is recorded in millis while the Session's timestamp is an Instant. During the transformation, Events perform this converstion using division. Before this change, the timestamp was truncated to the second, yet the code was trying to extract nanos which were always 0. This fixes that bug with a simple type change. I've also added a test to prevent regressions.
1 parent 8556d4a commit 2fcff3c

2 files changed

Lines changed: 21 additions & 11 deletions

File tree

core/src/main/java/com/google/adk/sessions/InMemorySessionService.java

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,13 @@ public Maybe<Session> getSession(
154154
if (config.numRecentEvents().isEmpty() && config.afterTimestamp().isPresent()) {
155155
Instant threshold = config.afterTimestamp().get();
156156

157-
eventsInCopy.removeIf(
158-
event -> getEventTimestampEpochSeconds(event) < threshold.getEpochSecond());
157+
eventsInCopy.removeIf(event -> getInstantFromEvent(event).isBefore(threshold));
159158
}
160159

161160
// Merge state into the potentially filtered copy and return
162161
return Maybe.just(mergeWithGlobalState(appName, userId, sessionCopy));
163162
}
164163

165-
// Helper to get event timestamp as epoch seconds
166-
private long getEventTimestampEpochSeconds(Event event) {
167-
return event.timestamp() / 1000L;
168-
}
169-
170164
@Override
171165
public Single<ListSessionsResponse> listSessions(String appName, String userId) {
172166
Objects.requireNonNull(appName, "appName cannot be null");
@@ -294,10 +288,7 @@ public Single<Event> appendEvent(Session session, Event event) {
294288
/** Converts an event's timestamp to an Instant. Adapt based on actual Event structure. */
295289
// TODO: have Event.timestamp() return Instant directly
296290
private Instant getInstantFromEvent(Event event) {
297-
double epochSeconds = getEventTimestampEpochSeconds(event);
298-
long seconds = (long) epochSeconds;
299-
long nanos = (long) ((epochSeconds % 1.0) * 1_000_000_000L);
300-
return Instant.ofEpochSecond(seconds, nanos);
291+
return Instant.ofEpochMilli(event.timestamp());
301292
}
302293

303294
/**

core/src/test/java/com/google/adk/sessions/InMemorySessionServiceTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.google.adk.events.Event;
2121
import com.google.adk.events.EventActions;
2222
import io.reactivex.rxjava3.core.Single;
23+
import java.time.Instant;
2324
import java.util.HashMap;
2425
import java.util.Optional;
2526
import java.util.concurrent.ConcurrentHashMap;
@@ -214,6 +215,24 @@ public void appendEvent_removesState() {
214215
assertThat(retrievedSessionRemove.state()).doesNotContainKey("temp:tempKey");
215216
}
216217

218+
@Test
219+
public void appendEvent_updatesSessionTimestampWithFractionalSeconds() {
220+
InMemorySessionService sessionService = new InMemorySessionService();
221+
Session session =
222+
sessionService.createSession("app", "user", new HashMap<>(), "session1").blockingGet();
223+
224+
// Add an event with a timestamp that contains a fractional second
225+
Event eventAdd = Event.builder().timestamp(5500).build();
226+
var unused = sessionService.appendEvent(session, eventAdd).blockingGet();
227+
228+
// Verify the last modified timestamp contains a fractional second
229+
Session retrievedSession =
230+
sessionService
231+
.getSession(session.appName(), session.userId(), session.id(), Optional.empty())
232+
.blockingGet();
233+
assertThat(retrievedSession.lastUpdateTime()).isEqualTo(Instant.ofEpochSecond(5, 500000000L));
234+
}
235+
217236
@Test
218237
public void sequentialAgents_shareTempState() {
219238
InMemorySessionService sessionService = new InMemorySessionService();

0 commit comments

Comments
 (0)