[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
This commit is contained in:
Sheldan
2021-12-24 23:41:27 +01:00
parent 9230a13218
commit ee01a3f07c
8 changed files with 133 additions and 77 deletions

View File

@@ -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<List<MuteEntry>> fromMutes(List<Mute> mutes) {
Map<ServerSpecificId, FutureMemberPair> loadedMutes = new HashMap<>();
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
mutes.forEach(mute -> {
CompletableFuture<Member> mutingMemberFuture = memberService.getMemberInServerAsync(mute.getMutingUser());
CompletableFuture<Member> mutedMemberFuture = memberService.getMemberInServerAsync(mute.getMutedUser());
AUserInAServer mutingUser = mute.getMutingUser();
AUserInAServer mutedUser = mute.getMutedUser();
CompletableFuture<Member> mutedFuture;
if(memberCaching.containsKey(mutedUser.getUserInServerId())) {
mutedFuture = memberCaching.get(mutedUser.getUserInServerId());
} else {
mutedFuture = memberService.getMemberInServerAsync(mutedUser);
memberCaching.put(mutedUser.getUserInServerId(), mutedFuture);
}
CompletableFuture<Member> 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<List<MuteEntry>> 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);

View File

@@ -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<List<NoteEntryModel>> fromNotes(List<UserNote> userNotes){
List<CompletableFuture<Member>> memberFutures = new ArrayList<>();
HashMap<ServerSpecificId, CompletableFuture<Member>> noteMemberMap = new HashMap<>();
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
userNotes.forEach(userNote -> {
CompletableFuture<Member> memberFuture = memberService.getMemberInServerAsync(userNote.getUser());
memberFutures.add(memberFuture);
noteMemberMap.put(userNote.getUserNoteId(), memberFuture);
AUserInAServer noteUser = userNote.getUser();
CompletableFuture<Member> 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<List<NoteEntryModel>> 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<Member> 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);
});

View File

@@ -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<List<WarnEntry>> fromWarnings(List<Warning> warnings) {
Map<ServerSpecificId, FutureMemberPair> loadedWarnings = new HashMap<>();
List<CompletableFuture<Member>> allFutures = new ArrayList<>();
Map<Long, CompletableFuture<Member>> memberCaching = new HashMap<>();
warnings.forEach(warning -> {
CompletableFuture<Member> warningMemberFuture = memberService.getMemberInServerAsync(warning.getWarningUser());
CompletableFuture<Member> warnedMemberFuture = memberService.getMemberInServerAsync(warning.getWarnedUser());
FutureMemberPair futurePair = FutureMemberPair.builder().firstMember(warningMemberFuture).secondMember(warnedMemberFuture).build();
AUserInAServer warningUser = warning.getWarningUser();
AUserInAServer warnedUser = warning.getWarnedUser();
CompletableFuture<Member> warnedFuture;
if(memberCaching.containsKey(warnedUser.getUserInServerId())) {
warnedFuture = memberCaching.get(warnedUser.getUserInServerId());
} else {
warnedFuture = memberService.getMemberInServerAsync(warnedUser);
memberCaching.put(warnedUser.getUserInServerId(), warnedFuture);
}
CompletableFuture<Member> 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<List<WarnEntry>> 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);
});

View File

@@ -82,11 +82,9 @@ public class UserNotesConverterTest {
List<NoteEntryModel> 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());
}
}

View File

@@ -111,18 +111,14 @@ public class WarnEntryConverterTest {
List<WarnEntry> 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());
}
}