Implement report caching

This commit is contained in:
Keir Nellyer 2016-06-10 00:28:07 +01:00
parent 22dbcbf90d
commit 4503f12738
2 changed files with 141 additions and 39 deletions

View File

@ -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));
}
/**

View File

@ -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<Integer, Report> _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<ReportMessage> 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<ReportMessage> 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<Integer, Report> entry : new HashSet<>(_cachedReports.entrySet()))
{
int reportId = entry.getKey();
Report report = entry.getValue();
Optional<Integer> handlerIdOptional = report.getHandlerId();
CompletableFuture<Boolean> 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<Boolean> shouldCacheReport(Report report)
{
return checkUserOnline(report.getSuspectId()).thenCompose(online ->
{
if (!online)
{
Optional<Integer> handlerIdOptional = report.getHandlerId();
if (handlerIdOptional.isPresent())
{
return checkUserOnline(handlerIdOptional.get());
}
else
{
return CompletableFuture.completedFuture(false);
}
}
return CompletableFuture.completedFuture(true);
});
}
private CompletableFuture<Boolean> checkUserOnline(int accountId)
{
return getAccountUUID(accountId).thenApply(Bukkit::getPlayer).thenApply(player -> player != null);
}
public CompletableFuture<String> getAccountName(int accountId)
{
return CompletableFuture.supplyAsync(() ->