diff --git a/src/main/java/com/commafeed/backend/DatabaseCleaner.java b/src/main/java/com/commafeed/backend/DatabaseCleaner.java index 39cc245c..cb502f0a 100644 --- a/src/main/java/com/commafeed/backend/DatabaseCleaner.java +++ b/src/main/java/com/commafeed/backend/DatabaseCleaner.java @@ -8,16 +8,33 @@ import javax.inject.Inject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.commafeed.backend.dao.FeedDAO; import com.commafeed.backend.dao.FeedEntryDAO; public class DatabaseCleaner { private static Logger log = LoggerFactory.getLogger(DatabaseCleaner.class); + @Inject + FeedDAO feedDAO; + @Inject FeedEntryDAO feedEntryDAO; - public long cleanOlderThan(long value, TimeUnit unit) { + public long cleanFeedsWithoutSubscriptions() { + + long total = 0; + int deleted = -1; + do { + deleted = feedDAO.deleteWithoutSubscriptions(100); + total += deleted; + log.info("removed {} feeds without subscriptions", total); + } while (deleted != 0); + log.info("cleanup done: {} feeds without subscriptions deleted", total); + return total; + } + + public long cleanEntriesOlderThan(long value, TimeUnit unit) { Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, -1 * (int) unit.toMinutes(value)); diff --git a/src/main/java/com/commafeed/backend/dao/FeedDAO.java b/src/main/java/com/commafeed/backend/dao/FeedDAO.java index a6f4645f..7067355d 100644 --- a/src/main/java/com/commafeed/backend/dao/FeedDAO.java +++ b/src/main/java/com/commafeed/backend/dao/FeedDAO.java @@ -10,12 +10,15 @@ import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; +import javax.persistence.criteria.SetJoin; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateUtils; import com.commafeed.backend.model.Feed; +import com.commafeed.backend.model.FeedSubscription; +import com.commafeed.backend.model.FeedSubscription_; import com.commafeed.backend.model.Feed_; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -92,4 +95,22 @@ public class FeedDAO extends GenericDAO { public List findByTopic(String topic) { return findByField(Feed_.pushTopicHash, DigestUtils.sha1Hex(topic)); } + + public int deleteWithoutSubscriptions(int max) { + CriteriaQuery query = builder.createQuery(getType()); + Root root = query.from(getType()); + + SetJoin join = root.join(Feed_.subscriptions, + JoinType.LEFT); + query.where(builder.isNull(join.get(FeedSubscription_.id))); + + TypedQuery q = em.createQuery(query); + q.setMaxResults(max); + + List list = q.getResultList(); + int deleted = list.size(); + delete(list); + return deleted; + + } } diff --git a/src/main/java/com/commafeed/backend/model/Feed.java b/src/main/java/com/commafeed/backend/model/Feed.java index e0a4c016..16f9dcc3 100644 --- a/src/main/java/com/commafeed/backend/model/Feed.java +++ b/src/main/java/com/commafeed/backend/model/Feed.java @@ -3,6 +3,7 @@ package com.commafeed.backend.model; import java.util.Date; import java.util.Set; +import javax.persistence.CascadeType; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.ManyToMany; @@ -97,7 +98,7 @@ public class Feed extends AbstractModel { @Column(length = 40) private String lastContentHash; - @ManyToMany(mappedBy = "feeds") + @ManyToMany(mappedBy = "feeds", cascade = CascadeType.REMOVE) private Set entries = Sets.newHashSet(); @OneToMany(mappedBy = "feed") diff --git a/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java b/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java index 115b8e0f..f14b68ff 100644 --- a/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java +++ b/src/main/java/com/commafeed/frontend/rest/resources/AdminREST.java @@ -195,9 +195,13 @@ public class AdminREST extends AbstractResourceREST { @Path("/cleanup") @GET - public Response cleanup() { - long deleted = cleaner.cleanOlderThan(30, TimeUnit.DAYS); - return Response.ok("ok: " + deleted).build(); + public Response cleanup(@QueryParam("days") @DefaultValue("30") int days) { + Map map = Maps.newHashMap(); + map.put("feeds_without_subscriptions", + cleaner.cleanFeedsWithoutSubscriptions()); + map.put("old entries", + cleaner.cleanEntriesOlderThan(days, TimeUnit.DAYS)); + return Response.ok(map).build(); } }