From 9e5148fa8c9105fffeef2ecc88ae44e5fedaa83a Mon Sep 17 00:00:00 2001 From: akastijn Date: Sun, 19 Jul 2026 19:20:38 +0200 Subject: [PATCH] Ensure unique timestamps for chat messages to prevent collisions and fix date formatting in chat-box UI. --- .../controllers/chat/ChatMessage.java | 4 +++- .../controllers/chat/ChatMessageMapper.java | 6 ++++-- .../altitudeweb/services/chat/ChatService.java | 16 +++++++++++++++- .../chat/components/chat/chat-box.component.html | 2 +- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessage.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessage.java index e9efba8..4825064 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessage.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessage.java @@ -2,6 +2,7 @@ package com.alttd.altitudeweb.controllers.chat; import lombok.Builder; import lombok.Getter; +import lombok.Setter; import java.time.Instant; import java.util.UUID; @@ -11,7 +12,8 @@ import java.util.UUID; public class ChatMessage { private final UUID uuid; - private final Instant timestamp; + @Setter + private Instant timestamp; private final String server; //TODO [Stijn] [2026-07-18]: Handle channel types //private final String channel; diff --git a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessageMapper.java b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessageMapper.java index 9469794..4184e3b 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessageMapper.java +++ b/backend/src/main/java/com/alttd/altitudeweb/controllers/chat/ChatMessageMapper.java @@ -4,16 +4,18 @@ import com.alttd.altitudeweb.database.chat.ChatLogDao; import com.alttd.altitudeweb.model.ChatMessageDto; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import lombok.experimental.UtilityClass; -import java.time.Instant; import java.util.UUID; @UtilityClass public class ChatMessageMapper { private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper() - .registerModule(new JavaTimeModule()); + .registerModule(new JavaTimeModule()) + .enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS); public ChatMessage fromDto(ChatMessageDto dto) { return ChatMessage.builder() diff --git a/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java b/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java index 3116120..6dcf0ad 100644 --- a/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java +++ b/backend/src/main/java/com/alttd/altitudeweb/services/chat/ChatService.java @@ -30,6 +30,7 @@ public class ChatService { private String[] allowedServers; private final NavigableMap chatMessages = new TreeMap<>(); private final EventPublisher eventPublisher; + private long lastMillis = 0; @Scheduled(cron = "0 * * * * *") public void clearOldMessages() { @@ -50,7 +51,8 @@ public class ChatService { try { sqlSession.getMapper(ChatLogMapper.class) .getChatLogs(Instant.now().minus(Duration.ofHours(1)).toEpochMilli()) - .stream().map(ChatMessageMapper::fromDao) + .stream() + .map(ChatMessageMapper::fromDao) .forEach(this::putChatMessage); } catch (Exception e) { log.error("Failed to load history count", e); @@ -58,7 +60,19 @@ public class ChatService { }); } + private synchronized void setUniqueTimestamp(ChatMessage chatMessage) { + long timestamp = chatMessage.getTimestamp().toEpochMilli(); + if (timestamp == lastMillis) { + timestamp += 1; + } else { + return; + } + lastMillis = timestamp; + chatMessage.setTimestamp(Instant.ofEpochMilli(timestamp)); + } + private void putChatMessage(ChatMessage chatMessage) { + setUniqueTimestamp(chatMessage); chatMessages.put(chatMessage.getTimestamp(), chatMessage); } diff --git a/frontend/src/app/pages/altitude/chat/components/chat/chat-box.component.html b/frontend/src/app/pages/altitude/chat/components/chat/chat-box.component.html index a74f664..70b8116 100644 --- a/frontend/src/app/pages/altitude/chat/components/chat/chat-box.component.html +++ b/frontend/src/app/pages/altitude/chat/components/chat/chat-box.component.html @@ -2,7 +2,7 @@ @for (message of messages(); track message.timestamp) {

- [{{ message.timestamp * 1000 | date: 'mediumTime' }}] + [{{ message.timestamp | date: 'mediumTime' }}]