Refactor: Add LobbyCleanupJob for periodic expired lobby cleanup
- isolate failures per lobby during cleanup - notify connected sessions about closed lobbies Refs #124 Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
+100
@@ -0,0 +1,100 @@
|
|||||||
|
package ch.unibas.dmi.dbis.cs108.casono.server.domain.lobby;
|
||||||
|
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.SuccessResponse;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.dispatcher.ResponseDispatcher;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.Session;
|
||||||
|
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionManager;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.List;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
/** Periodically removes expired empty lobbies and notifies connected sessions. */
|
||||||
|
public class LobbyCleanupJob implements Runnable {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(LobbyCleanupJob.class);
|
||||||
|
|
||||||
|
private final LobbyManager lobbyManager;
|
||||||
|
private final SessionManager sessionManager;
|
||||||
|
private final ResponseDispatcher responseDispatcher;
|
||||||
|
private final Duration expiryThreshold;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new cleanup job for expired empty lobbies.
|
||||||
|
*
|
||||||
|
* @param lobbyManager manager used to find and remove expired lobbies
|
||||||
|
* @param sessionManager manager used to resolve connected sessions
|
||||||
|
* @param responseDispatcher dispatcher used to notify clients about closed lobbies
|
||||||
|
* @param expiryThreshold age threshold that marks an empty lobby as expired
|
||||||
|
*/
|
||||||
|
public LobbyCleanupJob(
|
||||||
|
LobbyManager lobbyManager,
|
||||||
|
SessionManager sessionManager,
|
||||||
|
ResponseDispatcher responseDispatcher,
|
||||||
|
Duration expiryThreshold) {
|
||||||
|
this.lobbyManager = lobbyManager;
|
||||||
|
this.sessionManager = sessionManager;
|
||||||
|
this.responseDispatcher = responseDispatcher;
|
||||||
|
this.expiryThreshold = expiryThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs one cleanup cycle.
|
||||||
|
*
|
||||||
|
* <p>The method first fetches all expired empty lobbies. Each lobby is then processed
|
||||||
|
* independently so that a failure for one lobby does not stop the remaining cleanups.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LOGGER.debug("Job started.");
|
||||||
|
try {
|
||||||
|
List<LobbyId> expired;
|
||||||
|
try {
|
||||||
|
expired = lobbyManager.findEmptyLobbiesOlderThan(expiryThreshold);
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("Lobby expiry job failed: could not fetch expired lobbies", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (LobbyId lobbyId : expired) {
|
||||||
|
try {
|
||||||
|
lobbyManager.removeLobby(lobbyId);
|
||||||
|
broadcastLobbyClosed(lobbyId);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOGGER.warn("Failed to process expired lobby {}", lobbyId.value(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
LOGGER.debug("Job finished.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcasts a lobby-closed event to all currently connected sessions.
|
||||||
|
*
|
||||||
|
* @param lobbyId id of the lobby that was closed
|
||||||
|
*/
|
||||||
|
private void broadcastLobbyClosed(LobbyId lobbyId) {
|
||||||
|
for (Session session : sessionManager.getAllSessions()) {
|
||||||
|
try {
|
||||||
|
RequestContext ctx = new RequestContext(session.getId(), 0);
|
||||||
|
SuccessResponse event =
|
||||||
|
new SuccessResponse(
|
||||||
|
ctx,
|
||||||
|
ResponseBody.builder()
|
||||||
|
.param("EVENT", "LOBBY_CLOSED")
|
||||||
|
.param("LOBBY_ID", lobbyId.value())
|
||||||
|
.build()) {};
|
||||||
|
responseDispatcher.dispatch(event);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
LOGGER.warn(
|
||||||
|
"Failed to notify session {} about closed lobby {}",
|
||||||
|
session.getId().value(),
|
||||||
|
lobbyId.value(),
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user