From 4503f1273812f388ded2c973f86884d64676a190 Mon Sep 17 00:00:00 2001 From: Keir Nellyer Date: Fri, 10 Jun 2016 00:28:07 +0100 Subject: [PATCH] Implement report caching --- .../mineplex/core/report/ReportManager.java | 17 +- .../core/report/ReportRepository.java | 163 ++++++++++++++---- 2 files changed, 141 insertions(+), 39 deletions(-) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java index f63460baa..9bcef1d1e 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportManager.java @@ -47,7 +47,6 @@ public class ReportManager { private static final String NAME = "Report"; - // statistic constants private static final int ABUSE_BAN_THRESHOLD = 1; private JavaPlugin _javaPlugin; @@ -295,10 +294,13 @@ public class ReportManager _reportRepository.getOngoingReport(playerId) .thenCompose(_reportRepository::getReport) - .thenAccept(report -> { + .thenAccept(report -> + { if (report != null) { - sendHandlerNotification(report, F.main(getReportPrefix(report), String.format("%s has re-joined the game.", player.getName()))); + sendHandlerNotification(report, + F.main(getReportPrefix(report), + String.format("%s has re-joined the game.", player.getName()))); } } ); @@ -310,13 +312,18 @@ public class ReportManager _reportRepository.getOngoingReport(playerId) .thenCompose(_reportRepository::getReport) - .thenAccept(report -> { + .thenAccept(report -> + { if (report != null) { - sendHandlerNotification(report, F.main(getReportPrefix(report), String.format("%s has left the game.", player.getName()))); + sendHandlerNotification(report, + F.main(getReportPrefix(report), + String.format("%s has left the game.", player.getName()))); } } ); + + _reportRepository.clearCacheFor(_clientManager.getAccountId(player)); } /** diff --git a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java index 8b22b165d..ebfab1eb3 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/report/ReportRepository.java @@ -24,6 +24,7 @@ import mineplex.core.database.MinecraftRepository; import mineplex.serverdata.database.DBPool; import org.apache.commons.lang3.StringUtils; +import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; /** @@ -82,6 +83,8 @@ public class ReportRepository extends MinecraftRepository private static final String GET_ACCOUNT_UUID = "SELECT id, uuid FROM accounts" + " WHERE id IN (%s);"; + private final Map _cachedReports = new HashMap<>(); + public ReportRepository(JavaPlugin plugin) { super(plugin, DBPool.getAccount()); @@ -137,48 +140,63 @@ public class ReportRepository extends MinecraftRepository { if (reportId != -1) { - return CompletableFuture.supplyAsync(() -> + if (_cachedReports.containsKey(reportId)) { - try (Connection connection = DBPool.getAccount().getConnection()) + return CompletableFuture.completedFuture(_cachedReports.get(reportId)); + } + else + { + return CompletableFuture.supplyAsync(() -> { - PreparedStatement preparedStatement = connection.prepareStatement(GET_REPORT); - preparedStatement.setInt(1, reportId); - - ResultSet resultSet = preparedStatement.executeQuery(); - if (resultSet.next()) + try (Connection connection = DBPool.getAccount().getConnection()) { - int suspectId = resultSet.getInt("suspectId"); - ReportCategory reportCategory = ReportCategory.getById(resultSet.getInt("categoryId")); + PreparedStatement preparedStatement = connection.prepareStatement(GET_REPORT); + preparedStatement.setInt(1, reportId); - Report report = new Report(reportId, suspectId, reportCategory); - int handlerId = resultSet.getInt("handlerId"); - if (!resultSet.wasNull()) + ResultSet resultSet = preparedStatement.executeQuery(); + if (resultSet.next()) { - report.setHandlerId(handlerId); + int suspectId = resultSet.getInt("suspectId"); + ReportCategory reportCategory = ReportCategory.getById(resultSet.getInt("categoryId")); + + Report report = new Report(reportId, suspectId, reportCategory); + int handlerId = resultSet.getInt("handlerId"); + if (!resultSet.wasNull()) + { + report.setHandlerId(handlerId); + } + + Set reportMessages = getReportReasons(reportId).join(); + reportMessages.forEach(report::addReportReason); + + int resultId = resultSet.getInt("resultId"); + if (!resultSet.wasNull()) + { + ReportResultType resultType = ReportResultType.getById(resultId); + String reason = resultSet.getString("reason"); + Date closedTime = new Date(resultSet.getTimestamp("closedTime").getTime()); + report.setReportResult(new ReportResult(resultType, reason, closedTime)); + } + + shouldCacheReport(report).thenAccept(shouldCache -> + { + if (shouldCache) + { + _cachedReports.put(reportId, report); + } + }); + + return report; } - - Set reportMessages = getReportReasons(reportId).join(); - reportMessages.forEach(report::addReportReason); - - int resultId = resultSet.getInt("resultId"); - if (!resultSet.wasNull()) - { - ReportResultType resultType = ReportResultType.getById(resultId); - String reason = resultSet.getString("reason"); - Date closedTime = new Date(resultSet.getTimestamp("closedTime").getTime()); - report.setReportResult(new ReportResult(resultType, reason, closedTime)); - } - - return report; } - } - catch (SQLException e) - { - throw new RuntimeException(e); - } + catch (SQLException e) + { + throw new RuntimeException(e); + } - return null; - }); + return null; + }); + } } else { @@ -367,6 +385,83 @@ public class ReportRepository extends MinecraftRepository }); } + /** + * Disposes of cached reports which are cached as a result of this user. + * This function is called when a user leaves the server. + * + * @param accountId the account id to clean the cached reports of + */ + protected void clearCacheFor(int accountId) + { + for (Map.Entry entry : new HashSet<>(_cachedReports.entrySet())) + { + int reportId = entry.getKey(); + Report report = entry.getValue(); + Optional handlerIdOptional = report.getHandlerId(); + + CompletableFuture disposeCacheFuture = CompletableFuture.completedFuture(false); + + if (report.getSuspectId() == accountId) + { + if (handlerIdOptional.isPresent()) + { + disposeCacheFuture = checkUserOnline(handlerIdOptional.get()); + } + else + { + // no handler so un-cache this report + disposeCacheFuture = CompletableFuture.completedFuture(true); + } + } + else if (handlerIdOptional.isPresent() && handlerIdOptional.get() == accountId) + { + disposeCacheFuture = checkUserOnline(report.getSuspectId()); + } + + disposeCacheFuture.thenAccept(dispose -> + { + if (dispose) + { + _cachedReports.remove(reportId); + } + }); + } + } + + /** + * Checks if either the suspect or handler (if any) are online. + * If either are online then this will return true, otherwise false. + * + * @param report the report to check if it should be cached + * @return true if this report should be cached, false otherwise + */ + private CompletableFuture shouldCacheReport(Report report) + { + return checkUserOnline(report.getSuspectId()).thenCompose(online -> + { + if (!online) + { + Optional handlerIdOptional = report.getHandlerId(); + + if (handlerIdOptional.isPresent()) + { + return checkUserOnline(handlerIdOptional.get()); + } + else + { + return CompletableFuture.completedFuture(false); + } + } + + return CompletableFuture.completedFuture(true); + }); + } + + private CompletableFuture checkUserOnline(int accountId) + { + return getAccountUUID(accountId).thenApply(Bukkit::getPlayer).thenApply(player -> player != null); + } + public CompletableFuture getAccountName(int accountId) { return CompletableFuture.supplyAsync(() ->