From ee01a3f07c0a282c2bf0c16156b38349547cac73 Mon Sep 17 00:00:00 2001 From: Sheldan <5037282+Sheldan@users.noreply.github.com> Date: Fri, 24 Dec 2021 23:41:27 +0100 Subject: [PATCH] [AB-352] adding caching to the loading of members for warnings/user notes/mutes. this becomes relevant as members which left the guild are not cached by jda, which means, we retry it again improved models for templates to simplify the objects passed --- .../converter/MuteEntryConverter.java | 45 +++++++++++----- .../converter/UserNotesConverter.java | 43 +++++++++++----- .../converter/WarnEntryConverter.java | 51 +++++++++++++------ .../converter/UserNotesConverterTest.java | 6 +-- .../converter/WarnEntryConverterTest.java | 12 ++--- .../model/template/command/MuteEntry.java | 23 ++++----- .../template/command/NoteEntryModel.java | 12 +++-- .../model/template/command/WarnEntry.java | 18 ++++--- 8 files changed, 133 insertions(+), 77 deletions(-) diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/MuteEntryConverter.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/MuteEntryConverter.java index c07cffa7a..471138af0 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/MuteEntryConverter.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/MuteEntryConverter.java @@ -1,8 +1,9 @@ package dev.sheldan.abstracto.moderation.converter; import dev.sheldan.abstracto.core.models.FutureMemberPair; -import dev.sheldan.abstracto.core.models.MemberDisplayModel; import dev.sheldan.abstracto.core.models.ServerSpecificId; +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import dev.sheldan.abstracto.core.service.MemberService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.utils.FutureUtils; @@ -36,17 +37,32 @@ public class MuteEntryConverter { public CompletableFuture> fromMutes(List mutes) { Map loadedMutes = new HashMap<>(); List> allFutures = new ArrayList<>(); + Map> memberCaching = new HashMap<>(); mutes.forEach(mute -> { - CompletableFuture mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser()); - CompletableFuture mutedMemberFuture = memberService.getMemberInServerAsync(mute.getMutedUser()); + AUserInAServer mutingUser = mute.getMutingUser(); + AUserInAServer mutedUser = mute.getMutedUser(); + CompletableFuture mutedFuture; + if(memberCaching.containsKey(mutedUser.getUserInServerId())) { + mutedFuture = memberCaching.get(mutedUser.getUserInServerId()); + } else { + mutedFuture = memberService.getMemberInServerAsync(mutedUser); + memberCaching.put(mutedUser.getUserInServerId(), mutedFuture); + } + CompletableFuture mutingFuture; + if(memberCaching.containsKey(mutingUser.getUserInServerId())) { + mutingFuture = memberCaching.get(mutingUser.getUserInServerId()); + } else { + mutingFuture = memberService.getMemberInServerAsync(mutingUser); + memberCaching.put(mutingUser.getUserInServerId(), mutingFuture); + } FutureMemberPair futurePair = FutureMemberPair .builder() - .firstMember(mutingMemberFuture) - .secondMember(mutedMemberFuture) + .firstMember(mutingFuture) + .secondMember(mutedFuture) .build(); loadedMutes.put(mute.getMuteId(), futurePair); - allFutures.add(mutingMemberFuture); - allFutures.add(mutedMemberFuture); + allFutures.add(mutingFuture); + allFutures.add(mutedFuture); }); CompletableFuture> future = new CompletableFuture<>(); FutureUtils.toSingleFutureGeneric(allFutures) @@ -67,23 +83,28 @@ public class MuteEntryConverter { FutureMemberPair memberPair = loadedMuteInfo.get(muteInfo); Mute mute = muteManagementService.findMute(muteInfo.getId(), muteInfo.getServerId()); Member mutedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null; - MemberDisplayModel mutedUser = MemberDisplayModel + MemberDisplay mutedUser = MemberDisplay .builder() - .member(mutedMember) + .memberMention(mutedMember != null ? mutedMember.getAsMention() : null) .userId(mute.getMutedUser().getUserReference().getId()) + .serverId(mute.getServer().getId()) .build(); Member mutingMember = !memberPair.getFirstMember().isCompletedExceptionally() ? memberPair.getFirstMember().join() : null; - MemberDisplayModel mutingUser = MemberDisplayModel + MemberDisplay mutingUser = MemberDisplay .builder() - .member(mutingMember) + .memberMention(mutingMember != null ? mutingMember.getAsMention() : null) .userId(mute.getMutingUser().getUserReference().getId()) .build(); MuteEntry entry = MuteEntry .builder() .mutedUser(mutedUser) .mutingUser(mutingUser) - .mute(mute) + .muteId(mute.getMuteId().getId()) + .serverId(mute.getMuteId().getServerId()) + .reason(mute.getReason()) + .muteDate(mute.getMuteDate()) + .muteEnded(mute.getMuteEnded()) .muteDuration(Duration.between(mute.getMuteDate(), mute.getMuteTargetDate())) .build(); entries.add(entry); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverter.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverter.java index 67dc7404d..7c9cab7c9 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverter.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverter.java @@ -1,7 +1,8 @@ package dev.sheldan.abstracto.moderation.converter; -import dev.sheldan.abstracto.core.models.FullUserInServer; import dev.sheldan.abstracto.core.models.ServerSpecificId; +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import dev.sheldan.abstracto.core.service.MemberService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.utils.FutureUtils; @@ -37,18 +38,30 @@ public class UserNotesConverter { public CompletableFuture> fromNotes(List userNotes){ List> memberFutures = new ArrayList<>(); HashMap> noteMemberMap = new HashMap<>(); + Map> memberCaching = new HashMap<>(); userNotes.forEach(userNote -> { - CompletableFuture memberFuture = memberService.getMemberInServerAsync(userNote.getUser()); - memberFutures.add(memberFuture); - noteMemberMap.put(userNote.getUserNoteId(), memberFuture); + AUserInAServer noteUser = userNote.getUser(); + CompletableFuture noteFuture; + if(memberCaching.containsKey(noteUser.getUserInServerId())) { + noteFuture = memberCaching.get(noteUser.getUserInServerId()); + } else { + noteFuture = memberService.getMemberInServerAsync(noteUser); + memberCaching.put(noteUser.getUserInServerId(), noteFuture); + } + memberFutures.add(noteFuture); + noteMemberMap.put(userNote.getUserNoteId(), noteFuture); }); if(userNotes.isEmpty()) { memberFutures.add(CompletableFuture.completedFuture(null)); } - - return FutureUtils.toSingleFutureGeneric(memberFutures).thenApply(aVoid -> - self.loadFullNotes(noteMemberMap) - ); + CompletableFuture> future = new CompletableFuture<>(); + FutureUtils.toSingleFutureGeneric(memberFutures) + .whenComplete((unused, throwable) -> future.complete(self.loadFullNotes(noteMemberMap))) + .exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + }); + return future; } @Transactional @@ -58,15 +71,19 @@ public class UserNotesConverter { CompletableFuture memberFuture = futureHashMap.get(serverSpecificId); Member member = !memberFuture.isCompletedExceptionally() ? memberFuture.join() : null; UserNote note = userNoteManagementService.loadNote(serverSpecificId.getServerId(), serverSpecificId.getId()); - FullUserInServer fullUser = FullUserInServer + MemberDisplay display = MemberDisplay .builder() - .member(member) - .aUserInAServer(note.getUser()) + .userId(note.getUser().getUserReference().getId()) + .serverId(note.getServer().getId()) + .memberMention(member != null ? member.getAsMention() : null) .build(); NoteEntryModel entryModel = NoteEntryModel .builder() - .note(note) - .fullUser(fullUser) + .member(display) + .serverId(serverSpecificId.getServerId()) + .note(note.getNote()) + .noteId(note.getUserNoteId().getId()) + .created(note.getCreated()) .build(); entryModels.add(entryModel); }); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverter.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverter.java index cbc64bbaa..0da2f4f41 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverter.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/main/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverter.java @@ -1,8 +1,9 @@ package dev.sheldan.abstracto.moderation.converter; import dev.sheldan.abstracto.core.models.FutureMemberPair; -import dev.sheldan.abstracto.core.models.MemberDisplayModel; import dev.sheldan.abstracto.core.models.ServerSpecificId; +import dev.sheldan.abstracto.core.models.database.AUserInAServer; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import dev.sheldan.abstracto.core.service.MemberService; import dev.sheldan.abstracto.core.service.management.UserInServerManagementService; import dev.sheldan.abstracto.core.utils.FutureUtils; @@ -35,21 +36,36 @@ public class WarnEntryConverter { public CompletableFuture> fromWarnings(List warnings) { Map loadedWarnings = new HashMap<>(); List> allFutures = new ArrayList<>(); + Map> memberCaching = new HashMap<>(); warnings.forEach(warning -> { - CompletableFuture warningMemberFuture = memberService.getMemberInServerAsync(warning.getWarningUser()); - CompletableFuture warnedMemberFuture = memberService.getMemberInServerAsync(warning.getWarnedUser()); - FutureMemberPair futurePair = FutureMemberPair.builder().firstMember(warningMemberFuture).secondMember(warnedMemberFuture).build(); + AUserInAServer warningUser = warning.getWarningUser(); + AUserInAServer warnedUser = warning.getWarnedUser(); + CompletableFuture warnedFuture; + if(memberCaching.containsKey(warnedUser.getUserInServerId())) { + warnedFuture = memberCaching.get(warnedUser.getUserInServerId()); + } else { + warnedFuture = memberService.getMemberInServerAsync(warnedUser); + memberCaching.put(warnedUser.getUserInServerId(), warnedFuture); + } + CompletableFuture warningFuture; + if(memberCaching.containsKey(warningUser.getUserInServerId())) { + warningFuture = memberCaching.get(warningUser.getUserInServerId()); + } else { + warningFuture = memberService.getMemberInServerAsync(warningUser); + memberCaching.put(warningUser.getUserInServerId(), warningFuture); + } + FutureMemberPair futurePair = FutureMemberPair.builder().firstMember(warningFuture).secondMember(warnedFuture).build(); loadedWarnings.put(warning.getWarnId(), futurePair); - allFutures.add(warningMemberFuture); - allFutures.add(warnedMemberFuture); + allFutures.add(warningFuture); + allFutures.add(warnedFuture); }); CompletableFuture> future = new CompletableFuture<>(); FutureUtils.toSingleFutureGeneric(allFutures) .whenComplete((unused, throwable) -> future.complete(self.loadFullWarnEntries(loadedWarnings))) - .exceptionally(throwable -> { - future.completeExceptionally(throwable); - return null; - }); + .exceptionally(throwable -> { + future.completeExceptionally(throwable); + return null; + }); return future; } @@ -62,23 +78,28 @@ public class WarnEntryConverter { Warning warn = warnManagementService.findById(warning.getId(), warning.getServerId()); FutureMemberPair memberPair = loadedWarnInfo.get(warning); Member warnedMember = !memberPair.getSecondMember().isCompletedExceptionally() ? memberPair.getSecondMember().join() : null; - MemberDisplayModel warnedUser = MemberDisplayModel + MemberDisplay warnedUser = MemberDisplay .builder() - .member(warnedMember) + .memberMention(warnedMember != null ? warnedMember.getAsMention() : null) .userId(warn.getWarnedUser().getUserReference().getId()) .build(); Member warningMember = !memberPair.getFirstMember().isCompletedExceptionally() ? memberPair.getFirstMember().join() : null; - MemberDisplayModel warningUser = MemberDisplayModel + MemberDisplay warningUser = MemberDisplay .builder() - .member(warningMember) + .memberMention(warningMember != null ? warningMember.getAsMention() : null) .userId(warn.getWarningUser().getUserReference().getId()) .build(); WarnEntry entry = WarnEntry .builder() .warnedUser(warnedUser) .warningUser(warningUser) - .warning(warn) + .reason(warn.getReason()) + .decayDate(warn.getDecayDate()) + .decayed(warn.getDecayed()) + .warnId(warn.getWarnId().getId()) + .warnDate(warn.getWarnDate()) + .serverId(warn.getWarnId().getServerId()) .build(); entries.add(entry); }); diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverterTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverterTest.java index 118d3523c..b4237ab86 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverterTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/UserNotesConverterTest.java @@ -82,11 +82,9 @@ public class UserNotesConverterTest { List models = testUnit.loadFullNotes(map); Assert.assertEquals(2, models.size()); NoteEntryModel firstEntry = models.get(0); - Assert.assertEquals(member, firstEntry.getFullUser().getMember()); - Assert.assertEquals(userInAServer, firstEntry.getFullUser().getAUserInAServer()); + Assert.assertEquals(member, firstEntry.getMember()); NoteEntryModel secondEntry = models.get(1); - Assert.assertEquals(member, secondEntry.getFullUser().getMember()); - Assert.assertEquals(userInAServer, secondEntry.getFullUser().getAUserInAServer()); + Assert.assertEquals(member, secondEntry.getMember()); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverterTest.java b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverterTest.java index 4308ee8f9..7f469ed43 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverterTest.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-impl/src/test/java/dev/sheldan/abstracto/moderation/converter/WarnEntryConverterTest.java @@ -111,18 +111,14 @@ public class WarnEntryConverterTest { List models = testUnit.loadFullWarnEntries(map); Assert.assertEquals(2, models.size()); WarnEntry firstEntry = models.get(0); - Assert.assertEquals(warningMember, firstEntry.getWarningUser().getMember()); - Assert.assertEquals(warnedMember, firstEntry.getWarnedUser().getMember()); Assert.assertEquals(USER_ID_1, firstEntry.getWarnedUser().getUserId()); Assert.assertEquals(USER_ID_2, firstEntry.getWarningUser().getUserId()); - Assert.assertEquals(WARN_ID_1, firstEntry.getWarning().getWarnId().getId()); - Assert.assertEquals(SERVER_ID, firstEntry.getWarning().getWarnId().getServerId()); + Assert.assertEquals(WARN_ID_1, firstEntry.getWarnId()); + Assert.assertEquals(SERVER_ID, firstEntry.getServerId()); WarnEntry secondEntry = models.get(1); - Assert.assertEquals(warningMember, secondEntry.getWarningUser().getMember()); - Assert.assertEquals(warnedMember, secondEntry.getWarnedUser().getMember()); Assert.assertEquals(USER_ID_1, secondEntry.getWarnedUser().getUserId()); Assert.assertEquals(USER_ID_2, secondEntry.getWarningUser().getUserId()); - Assert.assertEquals(WARN_ID_2, secondEntry.getWarning().getWarnId().getId()); - Assert.assertEquals(SERVER_ID, secondEntry.getWarning().getWarnId().getServerId()); + Assert.assertEquals(WARN_ID_2, secondEntry.getWarnId()); + Assert.assertEquals(SERVER_ID, secondEntry.getServerId()); } } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/MuteEntry.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/MuteEntry.java index c5350b604..d24046caf 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/MuteEntry.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/MuteEntry.java @@ -1,28 +1,23 @@ package dev.sheldan.abstracto.moderation.model.template.command; -import dev.sheldan.abstracto.core.models.MemberDisplayModel; -import dev.sheldan.abstracto.moderation.model.database.Mute; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import lombok.Builder; import lombok.Getter; import lombok.Setter; import java.time.Duration; +import java.time.Instant; @Getter @Setter @Builder public class MuteEntry { - /** - * The {@link Mute} of this entry - */ - private Mute mute; - /** - * The {@link MemberDisplayModel} containing information about the user being muted. The member property is null if the user left the server - */ - private MemberDisplayModel mutedUser; - /** - * The {@link MemberDisplayModel} containing information about the user muting. The member property is null if the user left the server - */ - private MemberDisplayModel mutingUser; + private Long muteId; + private Long serverId; + private String reason; + private Instant muteDate; + private Boolean muteEnded; + private MemberDisplay mutedUser; + private MemberDisplay mutingUser; private Duration muteDuration; } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/NoteEntryModel.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/NoteEntryModel.java index 23f39b7aa..36a257010 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/NoteEntryModel.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/NoteEntryModel.java @@ -1,15 +1,19 @@ package dev.sheldan.abstracto.moderation.model.template.command; -import dev.sheldan.abstracto.core.models.FullUserInServer; -import dev.sheldan.abstracto.moderation.model.database.UserNote; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import java.time.Instant; + @Getter @Setter @Builder public class NoteEntryModel { - private UserNote note; - private FullUserInServer fullUser; + private String note; + private Long noteId; + private Instant created; + private MemberDisplay member; + private Long serverId; } diff --git a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/WarnEntry.java b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/WarnEntry.java index 0970ffb95..d30b15bf2 100644 --- a/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/WarnEntry.java +++ b/abstracto-application/abstracto-modules/moderation/moderation-int/src/main/java/dev/sheldan/abstracto/moderation/model/template/command/WarnEntry.java @@ -1,11 +1,13 @@ package dev.sheldan.abstracto.moderation.model.template.command; import dev.sheldan.abstracto.core.models.MemberDisplayModel; -import dev.sheldan.abstracto.moderation.model.database.Warning; +import dev.sheldan.abstracto.core.models.template.display.MemberDisplay; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import java.time.Instant; + /** * A single warning containing the full user instead of only the warning object when the warnings command is executed. * The template is: "warnings_warn_entry" @@ -14,16 +16,18 @@ import lombok.Setter; @Setter @Builder public class WarnEntry { - /** - * The {@link Warning} of this entry - */ - private Warning warning; + private String reason; + private Long warnId; + private Long serverId; + private Boolean decayed; + private Instant warnDate; + private Instant decayDate; /** * The {@link MemberDisplayModel} containing information about the user being warned. The member property is null if the user left the server */ - private MemberDisplayModel warnedUser; + private MemberDisplay warnedUser; /** * The {@link MemberDisplayModel} containing information about the user warning. The member property is null if the user left the server */ - private MemberDisplayModel warningUser; + private MemberDisplay warningUser; }