145 lines
4.5 KiB
Java
145 lines
4.5 KiB
Java
package com.lions.dev.service;
|
|
|
|
import com.lions.dev.dto.events.PresenceEvent;
|
|
import com.lions.dev.entity.users.Users;
|
|
import com.lions.dev.repository.UsersRepository;
|
|
import io.quarkus.logging.Log;
|
|
import jakarta.enterprise.context.ApplicationScoped;
|
|
import jakarta.enterprise.context.control.ActivateRequestContext;
|
|
import jakarta.inject.Inject;
|
|
import jakarta.transaction.Transactional;
|
|
import org.eclipse.microprofile.reactive.messaging.Channel;
|
|
import org.eclipse.microprofile.reactive.messaging.Emitter;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.ZoneOffset;
|
|
import java.util.*;
|
|
|
|
/**
|
|
* Service pour gérer la présence des utilisateurs (online/offline).
|
|
*
|
|
* Ce service gère:
|
|
* - Le marquage des utilisateurs comme en ligne/hors ligne
|
|
* - Le heartbeat pour maintenir le statut online
|
|
* - La diffusion de la présence aux amis via Kafka → WebSocket
|
|
*
|
|
* Architecture v2.0:
|
|
* PresenceService → Kafka Topic (presence.updates) → PresenceKafkaBridge → WebSocket → Client
|
|
*/
|
|
@ApplicationScoped
|
|
public class PresenceService {
|
|
|
|
@Inject
|
|
UsersRepository usersRepository;
|
|
|
|
@Inject
|
|
@Channel("presence")
|
|
Emitter<PresenceEvent> presenceEmitter; // v2.0 - Publie dans Kafka
|
|
|
|
/**
|
|
* Marque un utilisateur comme en ligne et broadcast sa présence.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
*/
|
|
@Transactional
|
|
public void setUserOnline(UUID userId) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user != null) {
|
|
user.updatePresence();
|
|
usersRepository.persist(user);
|
|
|
|
// Broadcast présence aux autres utilisateurs
|
|
broadcastPresenceToAll(userId, true, user.getLastSeen());
|
|
|
|
Log.debug("[PRESENCE] Utilisateur " + userId + " marqué online");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Marque un utilisateur comme hors ligne.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
*/
|
|
@Transactional
|
|
public void setUserOffline(UUID userId) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user != null) {
|
|
user.setOffline();
|
|
usersRepository.persist(user);
|
|
|
|
// Broadcast présence aux autres utilisateurs
|
|
broadcastPresenceToAll(userId, false, user.getLastSeen());
|
|
|
|
Log.debug("[PRESENCE] Utilisateur " + userId + " marqué offline");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Met à jour le heartbeat d'un utilisateur (keep-alive).
|
|
* Cette méthode est appelée depuis un thread worker, donc elle doit activer le contexte de requête.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
*/
|
|
@ActivateRequestContext
|
|
@Transactional
|
|
public void heartbeat(UUID userId) {
|
|
Users user = usersRepository.findById(userId);
|
|
if (user != null) {
|
|
user.updatePresence();
|
|
usersRepository.persist(user);
|
|
Log.debug("[PRESENCE] Heartbeat reçu pour utilisateur " + userId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Broadcast la présence d'un utilisateur via Kafka (v2.0).
|
|
* Le PresenceKafkaBridge consommera depuis Kafka et enverra via WebSocket.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
* @param isOnline Le statut online
|
|
* @param lastSeen La dernière fois que l'utilisateur était en ligne
|
|
*/
|
|
private void broadcastPresenceToAll(UUID userId, boolean isOnline, LocalDateTime lastSeen) {
|
|
try {
|
|
// Convertir LocalDateTime en timestamp (milliseconds)
|
|
Long lastSeenTimestamp = lastSeen != null
|
|
? lastSeen.toInstant(ZoneOffset.UTC).toEpochMilli()
|
|
: null;
|
|
|
|
// Créer l'événement de présence
|
|
PresenceEvent presenceEvent = new PresenceEvent(
|
|
userId.toString(),
|
|
isOnline ? "online" : "offline",
|
|
lastSeenTimestamp
|
|
);
|
|
|
|
// Publier dans Kafka (le bridge s'occupera de l'envoi WebSocket)
|
|
presenceEmitter.send(presenceEvent);
|
|
|
|
Log.debug("[PRESENCE] Événement de présence publié dans Kafka: " + userId + " -> " +
|
|
(isOnline ? "online" : "offline"));
|
|
} catch (Exception e) {
|
|
Log.error("[PRESENCE] Erreur lors de la publication de présence dans Kafka", e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupère le statut de présence d'un utilisateur.
|
|
*
|
|
* @param userId L'ID de l'utilisateur
|
|
* @return Map contenant isOnline et lastSeen
|
|
*/
|
|
public Map<String, Object> getUserPresence(UUID userId) {
|
|
Users user = usersRepository.findById(userId);
|
|
Map<String, Object> presence = new HashMap<>();
|
|
|
|
if (user != null) {
|
|
presence.put("userId", userId.toString());
|
|
presence.put("isOnline", user.isOnline());
|
|
presence.put("lastSeen", user.getLastSeen() != null ? user.getLastSeen().toString() : null);
|
|
}
|
|
|
|
return presence;
|
|
}
|
|
}
|