api: optimize pagination!!
Some checks failed
Deploy API / docker (17, 3.8.5) (push) Failing after 30s
Some checks failed
Deploy API / docker (17, 3.8.5) (push) Failing after 30s
This commit is contained in:
parent
1f1c55d41f
commit
131a5c2efe
@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@ -17,10 +18,15 @@ public class PaginationBuilder<T> {
|
||||
*/
|
||||
private int itemsPerPage;
|
||||
|
||||
/**
|
||||
* The total number of items.
|
||||
*/
|
||||
private int totalItems;
|
||||
|
||||
/**
|
||||
* The items to paginate.
|
||||
*/
|
||||
private List<T> items;
|
||||
private Function<FetchItems, List<T>> items;
|
||||
|
||||
/**
|
||||
* Sets the number of items per page.
|
||||
@ -33,14 +39,25 @@ public class PaginationBuilder<T> {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the total number of items.
|
||||
*
|
||||
* @param totalItems The total number of items.
|
||||
* @return The pagination builder.
|
||||
*/
|
||||
public PaginationBuilder<T> totalItems(Supplier<Integer> totalItems) {
|
||||
this.totalItems = totalItems.get();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the items to paginate.
|
||||
*
|
||||
* @param getItems The items to paginate.
|
||||
* @return The pagination builder.
|
||||
*/
|
||||
public PaginationBuilder<T> fillItems(Supplier<List<T>> getItems) {
|
||||
this.items = getItems.get();
|
||||
public PaginationBuilder<T> items(Function<FetchItems, List<T>> getItems) {
|
||||
this.items = getItems;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -56,23 +73,43 @@ public class PaginationBuilder<T> {
|
||||
/**
|
||||
* Gets a page of items.
|
||||
*
|
||||
* @param page The page number.
|
||||
* @param page The page number.
|
||||
* @return The page.
|
||||
*/
|
||||
public Page<T> getPage(int page) {
|
||||
int totalItems = this.items.size();
|
||||
int totalPages = (int) Math.ceil((double) totalItems / this.itemsPerPage);
|
||||
List<T> items = this.items.apply(new FetchItems(page, this.itemsPerPage));
|
||||
int totalPages = (int) Math.ceil((double) this.totalItems / this.itemsPerPage);
|
||||
|
||||
if (page < 1 || page > totalPages) {
|
||||
throw new BadRequestException("Invalid page number");
|
||||
}
|
||||
List<T> items = this.items.subList((page - 1) * this.itemsPerPage, Math.min(page * this.itemsPerPage, totalItems));
|
||||
return new Page<>(
|
||||
items,
|
||||
new Page.Metadata(page, totalPages, totalItems)
|
||||
new Page.Metadata(page, totalPages, this.totalItems)
|
||||
);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public static class FetchItems {
|
||||
/**
|
||||
* The current page.
|
||||
*/
|
||||
private final int currentPage;
|
||||
|
||||
/**
|
||||
* The items per page.
|
||||
*/
|
||||
private final int itemsPerPage;
|
||||
|
||||
/**
|
||||
* The amount of items to skip.
|
||||
*/
|
||||
public int skipAmount() {
|
||||
return (currentPage - 1) * itemsPerPage;
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
public static class Page<T> {
|
||||
|
@ -31,4 +31,18 @@ public class ScoreSaberScoreResponse extends ScoreSaberScore {
|
||||
this.user = user;
|
||||
this.leaderboard = leaderboard;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new score saber score response.
|
||||
*
|
||||
* @param score the score to create the response from
|
||||
* @param user the user that set the score
|
||||
* @param leaderboard the leaderboard the score was set on
|
||||
* @return the score saber score response
|
||||
*/
|
||||
public static ScoreSaberScoreResponse fromScore(ScoreSaberScore score, UserDTO user, Leaderboard leaderboard) {
|
||||
return new ScoreSaberScoreResponse(score.getId(), score.getPlayerId(), score.getPlatform(), score.getPlatformScoreId(), score.getLeaderboardId(),
|
||||
score.getRank(), score.getAccuracy(), score.getPp(), score.getScore(), score.getModifiers(), score.getMisses(), score.getBadCuts(),
|
||||
score.getDeviceInformation(), score.getTimestamp(), score.getWeight(), score.getMultiplier(), score.getMaxCombo(), user, leaderboard);
|
||||
}
|
||||
}
|
||||
|
@ -24,9 +24,10 @@ public interface ScoreRepository extends MongoRepository<Score, Long> {
|
||||
@Aggregation(pipeline = {
|
||||
"{ $match: { platform: ?0, pp: { $gt: 0 } } }",
|
||||
"{ $sort: { pp: -1 } }",
|
||||
"{ $skip: ?2 }",
|
||||
"{ $limit: ?1 }",
|
||||
})
|
||||
List<Score> getTopRankedScores(@NonNull Platform.Platforms platform, int amount);
|
||||
List<Score> getTopRankedScores(@NonNull Platform.Platforms platform, int amount, int skip);
|
||||
|
||||
/**
|
||||
* Gets all the ranked scores from the platform.
|
||||
|
@ -80,36 +80,17 @@ public class ScoreService {
|
||||
*/
|
||||
public PaginationBuilder.Page<ScoreSaberScoreResponse> getTopRankedScores(@NonNull Platform.Platforms platform, int pageNumber, boolean scoresOnly) {
|
||||
PaginationBuilder<ScoreSaberScoreResponse> builder = new PaginationBuilder<ScoreSaberScoreResponse>().build();
|
||||
builder.itemsPerPage(50);
|
||||
builder.fillItems(() -> {
|
||||
List<Score> foundScores = this.scoreRepository.getTopRankedScores(platform, 250);
|
||||
builder.itemsPerPage(15);
|
||||
builder.totalItems(() -> this.scoreRepository.getTotalRankedScores(platform));
|
||||
builder.items((fetchItems) -> {
|
||||
List<Score> foundScores = this.scoreRepository.getTopRankedScores(platform, fetchItems.getItemsPerPage(), fetchItems.skipAmount());
|
||||
List<ScoreSaberScoreResponse> scores = new ArrayList<>();
|
||||
for (Score score : foundScores) {
|
||||
ScoreSaberScore scoreSaberScore = (ScoreSaberScore) score;
|
||||
UserDTO user = scoresOnly ? null : userService.getUser(score.getPlayerId()).getAsDTO();
|
||||
Leaderboard leaderboard = scoresOnly ? null : Leaderboard.getFromScoreSaberToken(scoreSaberService.getLeaderboard(score.getLeaderboardId()));
|
||||
|
||||
scores.add(new ScoreSaberScoreResponse(
|
||||
score.getId(),
|
||||
score.getPlayerId(),
|
||||
score.getPlatform(),
|
||||
score.getPlatformScoreId(),
|
||||
score.getLeaderboardId(),
|
||||
score.getRank(),
|
||||
score.getAccuracy(),
|
||||
score.getPp(),
|
||||
score.getScore(),
|
||||
score.getModifiers(),
|
||||
score.getMisses(),
|
||||
score.getBadCuts(),
|
||||
score.getDeviceInformation(),
|
||||
score.getTimestamp(),
|
||||
scoreSaberScore.getWeight(),
|
||||
scoreSaberScore.getMultiplier(),
|
||||
scoreSaberScore.getMaxCombo(),
|
||||
user,
|
||||
leaderboard
|
||||
));
|
||||
scores.add(ScoreSaberScoreResponse.fromScore(scoreSaberScore, user, leaderboard));
|
||||
}
|
||||
return scores;
|
||||
});
|
||||
|
Reference in New Issue
Block a user