mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-04-15 12:10:21 +00:00
[AB-272] improving leaderboard performance
fixing leaderboard returning wrong pages making template cache update duration longer
This commit is contained in:
@@ -33,7 +33,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Shows the experience gain information of the top 10 users in the server, or if a page number is provided as a parameter, only the members which are on this page.
|
||||
@@ -69,18 +68,18 @@ public class LeaderBoardCommand extends AbstractConditionableCommand {
|
||||
AServer server = serverManagementService.loadServer(commandContext.getGuild());
|
||||
LeaderBoard leaderBoard = userExperienceService.findLeaderBoardData(server, page);
|
||||
LeaderBoardModel leaderBoardModel = (LeaderBoardModel) ContextConverter.slimFromCommandContext(commandContext, LeaderBoardModel.class);
|
||||
List<CompletableFuture<LeaderBoardEntryModel>> futures = new ArrayList<>();
|
||||
List<CompletableFuture<LeaderBoardEntryModel>> completableFutures = converter.fromLeaderBoard(leaderBoard);
|
||||
futures.addAll(completableFutures);
|
||||
List<CompletableFuture> futures = new ArrayList<>();
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> completableFutures = converter.fromLeaderBoard(leaderBoard);
|
||||
futures.add(completableFutures);
|
||||
log.info("Rendering leaderboard for page {} in server {} for user {}.", page, commandContext.getAuthor().getId(), commandContext.getGuild().getId());
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(aUserInAServer);
|
||||
CompletableFuture<LeaderBoardEntryModel> userRankFuture = converter.fromLeaderBoardEntry(userRank);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> userRankFuture = converter.fromLeaderBoardEntry(Arrays.asList(userRank));
|
||||
futures.add(userRankFuture);
|
||||
return FutureUtils.toSingleFutureGeneric(futures).thenCompose(aVoid -> {
|
||||
List<LeaderBoardEntryModel> finalModels = completableFutures.stream().map(CompletableFuture::join).collect(Collectors.toList());
|
||||
return FutureUtils.toSingleFuture(futures).thenCompose(aVoid -> {
|
||||
List<LeaderBoardEntryModel> finalModels = completableFutures.join();
|
||||
leaderBoardModel.setUserExperiences(finalModels);
|
||||
leaderBoardModel.setUserExecuting(userRankFuture.join());
|
||||
leaderBoardModel.setUserExecuting(userRankFuture.join().get(0));
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(LEADER_BOARD_POST_EMBED_TEMPLATE, leaderBoardModel, commandContext.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()));
|
||||
}).thenApply(aVoid -> CommandResult.fromIgnored());
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -70,13 +71,13 @@ public class Rank extends AbstractConditionableCommand {
|
||||
Member parameter = !parameters.isEmpty() ? (Member) parameters.get(0) : commandContext.getAuthor();
|
||||
AUserInAServer aUserInAServer = userInServerManagementService.loadOrCreateUser(parameter);
|
||||
LeaderBoardEntry userRank = userExperienceService.getRankOfUserInServer(aUserInAServer);
|
||||
CompletableFuture<LeaderBoardEntryModel> future = converter.fromLeaderBoardEntry(userRank);
|
||||
CompletableFuture<List<LeaderBoardEntryModel>> future = converter.fromLeaderBoardEntry(Arrays.asList(userRank));
|
||||
RankModel rankModel = RankModel
|
||||
.builder()
|
||||
.member(parameter)
|
||||
.build();
|
||||
return future.thenCompose(leaderBoardEntryModel ->
|
||||
self.renderAndSendRank(commandContext, rankModel, leaderBoardEntryModel)
|
||||
self.renderAndSendRank(commandContext, rankModel, leaderBoardEntryModel.get(0))
|
||||
).thenApply(result -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package dev.sheldan.abstracto.experience.converter;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoard;
|
||||
import dev.sheldan.abstracto.experience.model.LeaderBoardEntry;
|
||||
@@ -11,11 +10,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Converter used to convert from {@link LeaderBoard leaderBoard} to a list of {@link LeaderBoardEntryModel leaderBoardEntryModels}
|
||||
@@ -40,40 +42,36 @@ public class LeaderBoardModelConverter {
|
||||
* @return The list of {@link LeaderBoardEntryModel leaderboarEntryModels} which contain the fully fledged information provided to the
|
||||
* leader board template
|
||||
*/
|
||||
public List<CompletableFuture<LeaderBoardEntryModel>> fromLeaderBoard(LeaderBoard leaderBoard) {
|
||||
List<CompletableFuture<LeaderBoardEntryModel>> models = new ArrayList<>();
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoard(LeaderBoard leaderBoard) {
|
||||
log.debug("Converting {} entries to a list of leaderboard entries.", leaderBoard.getEntries().size());
|
||||
leaderBoard.getEntries().forEach(leaderBoardEntry -> {
|
||||
CompletableFuture<LeaderBoardEntryModel> entry = fromLeaderBoardEntry(leaderBoardEntry);
|
||||
models.add(entry);
|
||||
return fromLeaderBoardEntry(leaderBoard.getEntries());
|
||||
}
|
||||
|
||||
public CompletableFuture<List<LeaderBoardEntryModel>> fromLeaderBoardEntry(List<LeaderBoardEntry> leaderBoardEntries) {
|
||||
List<Long> userIds = new ArrayList<>();
|
||||
Long serverId = leaderBoardEntries.get(0).getExperience().getServer().getId();
|
||||
Map<Long, LeaderBoardEntryModel> models = leaderBoardEntries
|
||||
.stream()
|
||||
.map(leaderBoardEntry -> {
|
||||
AUserExperience experience = leaderBoardEntry.getExperience();
|
||||
Long userId = experience.getUser().getUserReference().getId();
|
||||
userIds.add(userId);
|
||||
return LeaderBoardEntryModel
|
||||
.builder()
|
||||
.userId(userId)
|
||||
.experience(experience.getExperience())
|
||||
.messageCount(experience.getMessageCount())
|
||||
.level(experience.getLevelOrDefault())
|
||||
.rank(leaderBoardEntry.getRank())
|
||||
.build();
|
||||
})
|
||||
.collect(Collectors.toMap(LeaderBoardEntryModel::getUserId, Function.identity()));
|
||||
return memberService.getMembersInServerAsync(serverId, userIds).thenApply(members -> {
|
||||
members.forEach(member -> models.get(member.getIdLong()).setMember(member));
|
||||
return new ArrayList<>(models.values())
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(LeaderBoardEntryModel::getRank)).
|
||||
collect(Collectors.toList());
|
||||
});
|
||||
return models;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@link LeaderBoardEntry entry} to a {@link LeaderBoardEntryModel model}, which provides a reference to the
|
||||
* {@link Member member} object of the given {@link AUserInAServer user} for convenience in the template
|
||||
* @param leaderBoardEntry The {@link LeaderBoardEntry entry} to be converted
|
||||
* @return The {@link LeaderBoardEntryModel model} accompanied with the {@link Member member} reference, might be null, if the
|
||||
* user left the guild
|
||||
*/
|
||||
public CompletableFuture<LeaderBoardEntryModel> fromLeaderBoardEntry(LeaderBoardEntry leaderBoardEntry) {
|
||||
AUserInAServer entryUser = leaderBoardEntry.getExperience().getUser();
|
||||
Long userInServerId = leaderBoardEntry.getExperience().getUser().getUserInServerId();
|
||||
Integer rank = leaderBoardEntry.getRank();
|
||||
return memberService.getMemberInServerAsync(entryUser.getServerReference().getId(), entryUser.getUserReference().getId())
|
||||
.thenApply(member -> self.buildLeaderBoardModel(userInServerId, member, rank))
|
||||
.exceptionally(throwable -> self.buildLeaderBoardModel(userInServerId, null, rank));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public LeaderBoardEntryModel buildLeaderBoardModel(Long userInServerId, Member member, Integer rank) {
|
||||
AUserExperience experience = userExperienceManagementService.findByUserInServerId(userInServerId);
|
||||
return LeaderBoardEntryModel
|
||||
.builder()
|
||||
.experience(experience)
|
||||
.member(member)
|
||||
.rank(rank)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -548,12 +548,13 @@ public class AUserExperienceServiceBean implements AUserExperienceService {
|
||||
page--;
|
||||
int pageSize = 10;
|
||||
log.debug("Loading leaderboard page {} for server {}.", page, server.getId());
|
||||
List<AUserExperience> experiences = userExperienceManagementService.findLeaderBoardUsersPaginated(server, page * pageSize, (page + 1) * pageSize);
|
||||
List<AUserExperience> experiences = userExperienceManagementService.findLeaderBoardUsersPaginated(server, page, pageSize);
|
||||
List<LeaderBoardEntry> entries = new ArrayList<>();
|
||||
log.debug("Found {} experiences.", experiences.size());
|
||||
int pageOffset = page * pageSize;
|
||||
for (int i = 0; i < experiences.size(); i++) {
|
||||
AUserExperience userExperience = experiences.get(i);
|
||||
entries.add(LeaderBoardEntry.builder().experience(userExperience).rank((page * pageSize) + i + 1).build());
|
||||
entries.add(LeaderBoardEntry.builder().experience(userExperience).rank(pageOffset + i + 1).build());
|
||||
}
|
||||
return LeaderBoard.builder().entries(entries).build();
|
||||
}
|
||||
|
||||
@@ -64,8 +64,8 @@ public class UserExperienceManagementServiceBean implements UserExperienceManage
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<AUserExperience> findLeaderBoardUsersPaginated(AServer aServer, Integer start, Integer end) {
|
||||
return repository.findTop10ByUser_ServerReferenceOrderByExperienceDesc(aServer, PageRequest.of(start, end));
|
||||
public List<AUserExperience> findLeaderBoardUsersPaginated(AServer aServer, Integer page, Integer size) {
|
||||
return repository.findTop10ByUser_ServerReferenceOrderByExperienceDesc(aServer, PageRequest.of(page, size));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user