Track chat session lifecycles: added session start/end times, database schema, and persistence logic.
This commit is contained in:
+44
-11
@@ -1,5 +1,10 @@
|
||||
package com.alttd.altitudeweb.services.chat.event_publisher;
|
||||
|
||||
import com.alttd.altitudeweb.database.Databases;
|
||||
import com.alttd.altitudeweb.database.web_db.KeyPairMapper;
|
||||
import com.alttd.altitudeweb.database.web_db.chat_session.ChatSession;
|
||||
import com.alttd.altitudeweb.database.web_db.chat_session.ChatSessionMapper;
|
||||
import com.alttd.altitudeweb.setup.Connection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
@@ -7,6 +12,8 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -27,19 +34,10 @@ public class EventPublisher {
|
||||
|
||||
emitterMap.computeIfAbsent(eventUser.uuid(), k -> new CopyOnWriteArrayList<>()).add(emitter);
|
||||
eventUserMap.put(eventUser.uuid(), eventUser);
|
||||
Instant sessionStart = Instant.now();
|
||||
log.info("User {} subscribed, active emitters: {}", eventUser.uuid(), countActive());
|
||||
|
||||
Runnable cleanup = () -> {
|
||||
List<SseEmitter> userEmitters = emitterMap.get(eventUser.uuid());
|
||||
if (userEmitters != null) {
|
||||
userEmitters.remove(emitter);
|
||||
if (userEmitters.isEmpty()) {
|
||||
emitterMap.remove(eventUser.uuid());
|
||||
eventUserMap.remove(eventUser.uuid());
|
||||
}
|
||||
}
|
||||
log.info("Cleaned up emitter for {}, active emitters: {}", eventUser.uuid(), countActive());
|
||||
};
|
||||
Runnable cleanup = () -> handleCleanup(eventUser, emitter, sessionStart);
|
||||
|
||||
// covers: clean disconnect (tab closed normally), server-side timeout, write failure
|
||||
emitter.onCompletion(cleanup);
|
||||
@@ -100,4 +98,39 @@ public class EventPublisher {
|
||||
sendToUser(emitter.uuid(), eventName, json);
|
||||
});
|
||||
}
|
||||
|
||||
private void handleCleanup(EventUser eventUser, SseEmitter emitter, Instant sessionStart) {
|
||||
List<SseEmitter> userEmitters = emitterMap.get(eventUser.uuid());
|
||||
if (userEmitters != null) {
|
||||
userEmitters.remove(emitter);
|
||||
if (userEmitters.isEmpty()) {
|
||||
emitterMap.remove(eventUser.uuid());
|
||||
eventUserMap.remove(eventUser.uuid());
|
||||
}
|
||||
}
|
||||
Instant sessionEnd = Instant.now();
|
||||
Duration between = Duration.between(sessionStart, sessionEnd);
|
||||
log.info("Cleaned up emitter for {}, active emitters: {}, session duration: {}",
|
||||
eventUser.uuid(), countActive(), between
|
||||
);
|
||||
ChatSession chatSession = ChatSession.builder()
|
||||
.uuid(eventUser.uuid())
|
||||
.session_start(sessionStart)
|
||||
.session_end(sessionEnd)
|
||||
.build();
|
||||
saveSession(chatSession);
|
||||
}
|
||||
|
||||
private void saveSession(ChatSession chatSession) {
|
||||
Connection.getConnection(Databases.DEFAULT)
|
||||
.runQuery(sqlSession -> {
|
||||
log.debug("Saving chat session");
|
||||
try {
|
||||
sqlSession.getMapper(ChatSessionMapper.class).storeSession(chatSession);
|
||||
log.debug("Saved chat session");
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to save chat session", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user