mirror of
https://github.com/Athou/commafeed.git
synced 2026-11-03 19:05:03 +00:00
speed up tree building by looking up unread counts in batches
This commit is contained in:
@@ -29,6 +29,7 @@ import org.apache.commons.collections4.CollectionUtils;
|
|||||||
|
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
@@ -238,19 +239,43 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
public Map<Long, UnreadCount> getUnreadCounts(List<FeedSubscription> subs) {
|
||||||
|
if (subs.isEmpty()) {
|
||||||
|
return Map.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Long, List<FeedSubscription>> subsByFeedId =
|
||||||
|
subs.stream().collect(Collectors.groupingBy(s -> s.getFeed().getId()));
|
||||||
|
|
||||||
JPAQuery<Tuple> query =
|
JPAQuery<Tuple> query =
|
||||||
query().select(ENTRY.count(), ENTRY.published.max())
|
query().select(ENTRY.feed.id, ENTRY.count(), ENTRY.published.max())
|
||||||
.from(ENTRY)
|
.from(ENTRY)
|
||||||
.leftJoin(ENTRY.statuses, STATUS)
|
.leftJoin(ENTRY.statuses, STATUS)
|
||||||
.on(STATUS.subscription.eq(sub))
|
.on(STATUS.subscription.in(subs))
|
||||||
.where(ENTRY.feed.eq(sub.getFeed()))
|
.where(ENTRY.feed.id.in(subsByFeedId.keySet()))
|
||||||
.where(buildUnreadPredicate());
|
.where(buildUnreadPredicate())
|
||||||
|
.groupBy(ENTRY.feed.id);
|
||||||
|
|
||||||
Tuple tuple = query.fetchOne();
|
setTimeout(query, config.database().queryTimeout());
|
||||||
Long count = tuple.get(ENTRY.count());
|
|
||||||
Instant published = tuple.get(ENTRY.published.max());
|
Map<Long, UnreadCount> result = new HashMap<>();
|
||||||
return new UnreadCount(sub.getId(), count == null ? 0 : count, published);
|
for (Tuple tuple : query.fetch()) {
|
||||||
|
Long feedId = tuple.get(ENTRY.feed.id);
|
||||||
|
Long count = tuple.get(ENTRY.count());
|
||||||
|
Instant published = tuple.get(ENTRY.published.max());
|
||||||
|
for (FeedSubscription sub : subsByFeedId.get(feedId)) {
|
||||||
|
result.put(
|
||||||
|
sub.getId(),
|
||||||
|
new UnreadCount(sub.getId(), count == null ? 0 : count, published));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// feeds with no unread entries are absent from the query result, default them to zero
|
||||||
|
for (FeedSubscription sub : subs) {
|
||||||
|
result.putIfAbsent(sub.getId(), new UnreadCount(sub.getId(), 0, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BooleanBuilder buildUnreadPredicate() {
|
private BooleanBuilder buildUnreadPredicate() {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Singleton
|
@Singleton
|
||||||
@@ -115,10 +114,7 @@ public class FeedSubscriptionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Map<Long, UnreadCount> getUnreadCount(User user) {
|
public Map<Long, UnreadCount> getUnreadCount(User user) {
|
||||||
return feedSubscriptionDAO.findAll(user).stream()
|
return feedEntryStatusDAO.getUnreadCounts(feedSubscriptionDAO.findAll(user));
|
||||||
.collect(
|
|
||||||
Collectors.toMap(
|
|
||||||
FeedSubscription::getId, feedEntryStatusDAO::getUnreadCount));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
|
|||||||
Reference in New Issue
Block a user