forked from Archives/Athou_commafeed
delete old statuses
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -15,7 +15,7 @@
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<production>false</production>
|
||||
<jpa.show_sql>false</jpa.show_sql>
|
||||
<jpa.show_sql>true</jpa.show_sql>
|
||||
<jpa.datasource.name>java:openejb/Resource/My DataSource</jpa.datasource.name>
|
||||
<jpa.cache>false</jpa.cache>
|
||||
<jpa.table.encoding>utf8mb4</jpa.table.encoding>
|
||||
|
||||
@@ -14,10 +14,11 @@ import javax.persistence.criteria.Path;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.hibernate.Criteria;
|
||||
import org.hibernate.criterion.Disjunction;
|
||||
import org.hibernate.criterion.MatchMode;
|
||||
import org.hibernate.criterion.Order;
|
||||
import org.hibernate.criterion.ProjectionList;
|
||||
import org.hibernate.criterion.Projections;
|
||||
@@ -80,8 +81,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
List<FeedEntryStatus> statuses = em.createQuery(query).getResultList();
|
||||
FeedEntryStatus status = Iterables.getFirst(statuses, null);
|
||||
if (status == null) {
|
||||
Date unreadThreshold = getUnreadThreshold();
|
||||
boolean read = unreadThreshold == null ? false : entry
|
||||
.getInserted().before(unreadThreshold);
|
||||
status = new FeedEntryStatus(sub.getUser(), sub, entry);
|
||||
status.setRead(false);
|
||||
status.setRead(read);
|
||||
status.setMarkable(!read);
|
||||
} else {
|
||||
status.setMarkable(true);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -134,30 +141,33 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
FeedEntry_.content.getName(), "content",
|
||||
JoinType.INNER_JOIN);
|
||||
|
||||
String joinedKeywords = StringUtils.join(keywords.toLowerCase()
|
||||
.split(" "), "%");
|
||||
joinedKeywords = "%" + joinedKeywords + "%";
|
||||
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.content.getName(),
|
||||
joinedKeywords));
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.title.getName(),
|
||||
joinedKeywords));
|
||||
contentJoin.add(or);
|
||||
for (String keyword : keywords.split(" ")) {
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.content.getName(),
|
||||
keyword, MatchMode.ANYWHERE));
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.title.getName(),
|
||||
keyword, MatchMode.ANYWHERE));
|
||||
contentJoin.add(or);
|
||||
}
|
||||
}
|
||||
|
||||
if (unreadOnly) {
|
||||
|
||||
Criteria statusJoin = criteria.createCriteria(FeedEntry_.statuses
|
||||
.getName(), "status", JoinType.LEFT_OUTER_JOIN,
|
||||
Restrictions.eq(FeedEntryStatus_.subscription.getName(),
|
||||
sub));
|
||||
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(Restrictions.isNull(FeedEntryStatus_.id.getName()));
|
||||
or.add(Restrictions.isNull(FeedEntryStatus_.read.getName()));
|
||||
or.add(Restrictions.eq(FeedEntryStatus_.read.getName(), false));
|
||||
|
||||
statusJoin.add(or);
|
||||
|
||||
Date unreadThreshold = getUnreadThreshold();
|
||||
if (unreadThreshold != null) {
|
||||
criteria.add(Restrictions.ge(FeedEntry_.inserted.getName(),
|
||||
unreadThreshold));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (last != null) {
|
||||
@@ -175,11 +185,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
if (order != null) {
|
||||
Order o = null;
|
||||
if (order == ReadingOrder.asc) {
|
||||
o = Order.asc(FeedEntry_.updated.getName());
|
||||
o = Order.asc(FeedFeedEntry_.entryUpdated.getName());
|
||||
} else {
|
||||
o = Order.desc(FeedEntry_.updated.getName());
|
||||
o = Order.desc(FeedFeedEntry_.entryUpdated.getName());
|
||||
}
|
||||
criteria.addOrder(o);
|
||||
ffeJoin.addOrder(o);
|
||||
}
|
||||
if (offset > -1) {
|
||||
criteria.setFirstResult(offset);
|
||||
@@ -235,6 +245,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return lazyLoadContent(includeContent, results);
|
||||
}
|
||||
|
||||
private Date getUnreadThreshold() {
|
||||
int keepStatusDays = applicationSettingsService.get()
|
||||
.getKeepStatusDays();
|
||||
return keepStatusDays > 0 ? DateUtils.addMinutes(new Date(), -1
|
||||
* keepStatusDays) : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Long getUnreadCount(FeedSubscription subscription) {
|
||||
Long count = null;
|
||||
|
||||
@@ -35,6 +35,7 @@ public class ApplicationSettings extends AbstractModel {
|
||||
private boolean imageProxyEnabled;
|
||||
private int queryTimeout;
|
||||
private boolean crawlingPaused;
|
||||
private int keepStatusDays = 0;
|
||||
|
||||
@Column(length = 255)
|
||||
private String announcement;
|
||||
@@ -200,4 +201,12 @@ public class ApplicationSettings extends AbstractModel {
|
||||
this.crawlingPaused = crawlingPaused;
|
||||
}
|
||||
|
||||
public int getKeepStatusDays() {
|
||||
return keepStatusDays;
|
||||
}
|
||||
|
||||
public void setKeepStatusDays(int keepStatusDays) {
|
||||
this.keepStatusDays = keepStatusDays;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
@@ -34,6 +35,9 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
private boolean read;
|
||||
private boolean starred;
|
||||
|
||||
@Transient
|
||||
private boolean markable;
|
||||
|
||||
/**
|
||||
* Denormalization starts here
|
||||
*/
|
||||
@@ -52,7 +56,8 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
|
||||
}
|
||||
|
||||
public FeedEntryStatus(User user, FeedSubscription subscription, FeedEntry entry) {
|
||||
public FeedEntryStatus(User user, FeedSubscription subscription,
|
||||
FeedEntry entry) {
|
||||
setUser(user);
|
||||
setSubscription(subscription);
|
||||
setEntry(entry);
|
||||
@@ -116,4 +121,12 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public boolean isMarkable() {
|
||||
return markable;
|
||||
}
|
||||
|
||||
public void setMarkable(boolean markable) {
|
||||
this.markable = markable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.commafeed.backend.services;
|
||||
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.Query;
|
||||
|
||||
@Stateless
|
||||
public class CleaningService {
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
@PersistenceContext
|
||||
EntityManager em;
|
||||
|
||||
// @Schedule(hour = "*")
|
||||
protected void cleanOldStatuses() {
|
||||
int keepStatusDays = applicationSettingsService.get()
|
||||
.getKeepStatusDays();
|
||||
if (keepStatusDays > 0) {
|
||||
Query query = em.createNamedQuery("Statuses.deleteOld");
|
||||
query.executeUpdate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ public class Entry implements Serializable {
|
||||
|
||||
entry.setRead(status.isRead());
|
||||
entry.setStarred(status.isStarred());
|
||||
entry.setMarkable(status.isMarkable());
|
||||
|
||||
entry.setId(String.valueOf(feedEntry.getId()));
|
||||
entry.setGuid(feedEntry.getGuid());
|
||||
@@ -124,6 +125,9 @@ public class Entry implements Serializable {
|
||||
@ApiProperty("starred status")
|
||||
private boolean starred;
|
||||
|
||||
@ApiProperty("wether the entry is still markable (old entry statuses are discarded)")
|
||||
private boolean markable;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
@@ -268,4 +272,12 @@ public class Entry implements Serializable {
|
||||
this.insertedDate = insertedDate;
|
||||
}
|
||||
|
||||
public boolean isMarkable() {
|
||||
return markable;
|
||||
}
|
||||
|
||||
public void setMarkable(boolean markable) {
|
||||
this.markable = markable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,21 +4,9 @@
|
||||
xsi:schemaLocation="
|
||||
http://java.sun.com/xml/ns/persistence/orm
|
||||
http://java.sun.com/xml/ns/persistence/orm_2_0.xsd">
|
||||
|
||||
<named-query name="EntryStatus.unreadCounts">
|
||||
<query>select s.subscription.id, count(s) from FeedEntryStatus s where s.user=:user and s.read=false group by s.subscription.id</query>
|
||||
|
||||
<named-query name="Statuses.deleteOld">
|
||||
<query>delete from FeedEntryStatus s where s.entryInserted < :date and s.starred = false</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="EntryStatus.existing">
|
||||
<query>select new com.commafeed.backend.dao.FeedEntryDAO$EntryWithFeed(e, f) FROM FeedEntry e LEFT JOIN e.feedRelationships f WITH f.feed.id = :feedId where e.guidHash = :guidHash and e.url = :url</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="EntryStatus.deleteByIds">
|
||||
<query>delete from FeedEntryStatus s where s.id in :ids</query>
|
||||
</named-query>
|
||||
|
||||
<named-query name="Feed.deleteEntryRelationships">
|
||||
<query>delete from FeedFeedEntry ffe where ffe.feed.id = :feedId</query>
|
||||
</named-query>
|
||||
|
||||
|
||||
</entity-mappings>
|
||||
@@ -346,4 +346,13 @@
|
||||
<column name="subscription_id" />
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="athou" id="add-trim-status-setting">
|
||||
<addColumn tableName="APPLICATIONSETTINGS">
|
||||
<column name="keepStatusDays" type="INT" />
|
||||
</addColumn>
|
||||
<update tableName="APPLICATIONSETTINGS">
|
||||
<column name="keepStatusDays" valueNumeric="0"></column>
|
||||
</update>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
|
||||
@@ -163,6 +163,14 @@
|
||||
ng-model="settings.queryTimeout" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="keepStatusDays">Keep read status for (days)</label>
|
||||
<div class="controls">
|
||||
<input type="number" name="keepStatusDays" class="input-block-level"
|
||||
ng-model="settings.keepStatusDays" />
|
||||
<span class="help-inline">0 = keep forever</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="crawlingPaused">Pause crawling</label>
|
||||
<div class="controls">
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
<i ng-class="{'icon-star icon-star-yellow': entry.starred, 'icon-star-empty': !entry.starred}"
|
||||
class="pointer"></i>
|
||||
</span>
|
||||
<label class="checkbox inline">
|
||||
<label class="checkbox inline" ui-if="entry.markable">
|
||||
<input type="checkbox" ng-checked="!entry.read" ng-click="mark(entry, !entry.read)" class="mousetrap"></input>
|
||||
${view.keep_unread}
|
||||
</label>
|
||||
|
||||
Reference in New Issue
Block a user