if under heavy load, don't refresh feeds for users who logged in more than a month ago for the last time

This commit is contained in:
Athou
2013-08-01 21:11:45 +02:00
parent cb1b99815c
commit 71403d4174
3 changed files with 42 additions and 9 deletions

View File

@@ -7,11 +7,13 @@ import javax.ejb.Stateless;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType; import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Path; import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin; import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import javax.persistence.metamodel.SingularAttribute; import javax.persistence.metamodel.SingularAttribute;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
@@ -25,6 +27,8 @@ import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedSubscription; import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.model.FeedSubscription_; import com.commafeed.backend.model.FeedSubscription_;
import com.commafeed.backend.model.Feed_; import com.commafeed.backend.model.Feed_;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.User_;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@@ -38,30 +42,45 @@ public class FeedDAO extends GenericDAO<Feed> {
public List<Feed> feeds; public List<Feed> feeds;
} }
private Predicate getUpdatablePredicate(Root<Feed> root) { private List<Predicate> getUpdatablePredicates(CriteriaQuery<?> query, Root<Feed> root, Date lastLoginThreshold) {
List<Predicate> preds = Lists.newArrayList();
Predicate isNull = builder.isNull(root.get(Feed_.disabledUntil)); Predicate isNull = builder.isNull(root.get(Feed_.disabledUntil));
Predicate lessThan = builder.lessThan(root.get(Feed_.disabledUntil), new Date()); Predicate lessThan = builder.lessThan(root.get(Feed_.disabledUntil), new Date());
preds.add(builder.or(isNull, lessThan));
return builder.or(isNull, lessThan); if (lastLoginThreshold != null) {
Subquery<Long> subquery = query.subquery(Long.class);
Root<FeedSubscription> subroot = subquery.from(FeedSubscription.class);
subquery.select(builder.count(subroot.get(FeedSubscription_.id)));
Join<FeedSubscription, User> userJoin = subroot.join(FeedSubscription_.user);
Predicate p1 = builder.equal(subroot.get(FeedSubscription_.feed), root);
Predicate p2 = builder.greaterThanOrEqualTo(userJoin.get(User_.lastLogin), lastLoginThreshold);
subquery.where(p1, p2);
preds.add(builder.exists(subquery));
}
return preds;
} }
public Long getUpdatableCount() { public Long getUpdatableCount(Date lastLoginThreshold) {
CriteriaQuery<Long> query = builder.createQuery(Long.class); CriteriaQuery<Long> query = builder.createQuery(Long.class);
Root<Feed> root = query.from(getType()); Root<Feed> root = query.from(getType());
query.select(builder.count(root)); query.select(builder.count(root));
query.where(getUpdatablePredicate(root)); query.where(getUpdatablePredicates(query, root, lastLoginThreshold).toArray(new Predicate[0]));
TypedQuery<Long> q = em.createQuery(query); TypedQuery<Long> q = em.createQuery(query);
return q.getSingleResult(); return q.getSingleResult();
} }
public List<Feed> findNextUpdatable(int count) { public List<Feed> findNextUpdatable(int count, Date lastLoginThreshold) {
CriteriaQuery<Feed> query = builder.createQuery(getType()); CriteriaQuery<Feed> query = builder.createQuery(getType());
Root<Feed> root = query.from(getType()); Root<Feed> root = query.from(getType());
query.where(getUpdatablePredicate(root)); query.where(getUpdatablePredicates(query, root, lastLoginThreshold).toArray(new Predicate[0]));
query.orderBy(builder.asc(root.get(Feed_.disabledUntil))); query.orderBy(builder.asc(root.get(Feed_.disabledUntil)));
TypedQuery<Feed> q = em.createQuery(query); TypedQuery<Feed> q = em.createQuery(query);

View File

@@ -122,7 +122,7 @@ public class FeedRefreshTaskGiver {
} }
public Long getUpdatableCount() { public Long getUpdatableCount() {
return feedDAO.getUpdatableCount(); return feedDAO.getUpdatableCount(getLastLoginThreshold());
} }
/** /**
@@ -139,12 +139,12 @@ public class FeedRefreshTaskGiver {
* refills the refresh queue and empties the giveBack queue while at it * refills the refresh queue and empties the giveBack queue while at it
*/ */
private void refill() { private void refill() {
int count = Math.min(300, 3 * backgroundThreads); int count = Math.min(100, 3 * backgroundThreads);
// first, get feeds that are up to refresh from the database // first, get feeds that are up to refresh from the database
List<FeedRefreshContext> contexts = Lists.newArrayList(); List<FeedRefreshContext> contexts = Lists.newArrayList();
if (!applicationSettingsService.get().isCrawlingPaused()) { if (!applicationSettingsService.get().isCrawlingPaused()) {
List<Feed> feeds = feedDAO.findNextUpdatable(count); List<Feed> feeds = feedDAO.findNextUpdatable(count, getLastLoginThreshold());
for (Feed feed : feeds) { for (Feed feed : feeds) {
contexts.add(new FeedRefreshContext(feed, false)); contexts.add(new FeedRefreshContext(feed, false));
} }
@@ -195,4 +195,12 @@ public class FeedRefreshTaskGiver {
giveBackQueue.add(feed); giveBackQueue.add(feed);
} }
private Date getLastLoginThreshold() {
if (applicationSettingsService.get().isHeavyLoad()) {
return DateUtils.addDays(new Date(), -30);
} else {
return null;
}
}
} }

View File

@@ -129,4 +129,10 @@
</update> </update>
</changeSet> </changeSet>
<changeSet author="athou" id="add-last-login-index">
<createIndex tableName="USERS" indexName="lastlogin_index">
<column name="lastLogin" />
</createIndex>
</changeSet>
</databaseChangeLog> </databaseChangeLog>