mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
remove redis as caching is no longer needed now
This commit is contained in:
@@ -1,39 +0,0 @@
|
||||
package com.commafeed.backend.cache;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.commafeed.backend.Digests;
|
||||
import com.commafeed.backend.feed.parser.FeedParserResult.Entry;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.model.Category;
|
||||
import com.commafeed.frontend.model.UnreadCount;
|
||||
|
||||
public abstract class CacheService {
|
||||
|
||||
// feed entries for faster refresh
|
||||
public abstract Set<String> getLastEntries(Feed feed);
|
||||
|
||||
public abstract void setLastEntries(Feed feed, List<String> entries);
|
||||
|
||||
public String buildUniqueEntryKey(Entry entry) {
|
||||
return Digests.sha1Hex(entry.guid() + entry.url());
|
||||
}
|
||||
|
||||
// user categories
|
||||
public abstract Category getUserRootCategory(User user);
|
||||
|
||||
public abstract void setUserRootCategory(User user, Category category);
|
||||
|
||||
public abstract void invalidateUserRootCategory(User... users);
|
||||
|
||||
// unread count
|
||||
public abstract UnreadCount getUnreadCount(FeedSubscription sub);
|
||||
|
||||
public abstract void setUnreadCount(FeedSubscription sub, UnreadCount count);
|
||||
|
||||
public abstract void invalidateUnreadCount(FeedSubscription... subs);
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package com.commafeed.backend.cache;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.model.Category;
|
||||
import com.commafeed.frontend.model.UnreadCount;
|
||||
|
||||
public class NoopCacheService extends CacheService {
|
||||
|
||||
@Override
|
||||
public Set<String> getLastEntries(Feed feed) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastEntries(Feed feed, List<String> entries) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnreadCount(FeedSubscription sub, UnreadCount count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateUnreadCount(FeedSubscription... subs) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getUserRootCategory(User user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRootCategory(User user, Category category) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateUserRootCategory(User... users) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package com.commafeed.backend.cache;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.model.Category;
|
||||
import com.commafeed.frontend.model.UnreadCount;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.Pipeline;
|
||||
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class RedisCacheService extends CacheService {
|
||||
|
||||
private static final ObjectMapper MAPPER = new ObjectMapper().registerModule(new JavaTimeModule());
|
||||
|
||||
private final JedisPool pool;
|
||||
|
||||
@Override
|
||||
public Set<String> getLastEntries(Feed feed) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisEntryKey(feed);
|
||||
return jedis.smembers(key);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastEntries(Feed feed, List<String> entries) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisEntryKey(feed);
|
||||
|
||||
Pipeline pipe = jedis.pipelined();
|
||||
pipe.del(key);
|
||||
for (String entry : entries) {
|
||||
pipe.sadd(key, entry);
|
||||
}
|
||||
pipe.expire(key, (int) TimeUnit.DAYS.toSeconds(7));
|
||||
pipe.sync();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Category getUserRootCategory(User user) {
|
||||
Category cat = null;
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisUserRootCategoryKey(user);
|
||||
String json = jedis.get(key);
|
||||
if (json != null) {
|
||||
cat = MAPPER.readValue(json, Category.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return cat;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUserRootCategory(User user, Category category) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisUserRootCategoryKey(user);
|
||||
|
||||
Pipeline pipe = jedis.pipelined();
|
||||
pipe.del(key);
|
||||
pipe.set(key, MAPPER.writeValueAsString(category));
|
||||
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
||||
pipe.sync();
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public UnreadCount getUnreadCount(FeedSubscription sub) {
|
||||
UnreadCount count = null;
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisUnreadCountKey(sub);
|
||||
String json = jedis.get(key);
|
||||
if (json != null) {
|
||||
count = MAPPER.readValue(json, UnreadCount.class);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnreadCount(FeedSubscription sub, UnreadCount count) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
String key = buildRedisUnreadCountKey(sub);
|
||||
|
||||
Pipeline pipe = jedis.pipelined();
|
||||
pipe.del(key);
|
||||
pipe.set(key, MAPPER.writeValueAsString(count));
|
||||
pipe.expire(key, (int) TimeUnit.MINUTES.toSeconds(30));
|
||||
pipe.sync();
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateUserRootCategory(User... users) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
Pipeline pipe = jedis.pipelined();
|
||||
if (users != null) {
|
||||
for (User user : users) {
|
||||
String key = buildRedisUserRootCategoryKey(user);
|
||||
pipe.del(key);
|
||||
}
|
||||
}
|
||||
pipe.sync();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateUnreadCount(FeedSubscription... subs) {
|
||||
try (Jedis jedis = pool.getResource()) {
|
||||
Pipeline pipe = jedis.pipelined();
|
||||
if (subs != null) {
|
||||
for (FeedSubscription sub : subs) {
|
||||
String key = buildRedisUnreadCountKey(sub);
|
||||
pipe.del(key);
|
||||
}
|
||||
}
|
||||
pipe.sync();
|
||||
}
|
||||
}
|
||||
|
||||
private String buildRedisEntryKey(Feed feed) {
|
||||
return "f:" + Models.getId(feed);
|
||||
}
|
||||
|
||||
private String buildRedisUserRootCategoryKey(User user) {
|
||||
return "c:" + Models.getId(user);
|
||||
}
|
||||
|
||||
private String buildRedisUnreadCountKey(FeedSubscription sub) {
|
||||
return "u:" + Models.getId(sub);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.commafeed.backend.feed;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -16,7 +15,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import com.codahale.metrics.Meter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.commafeed.backend.Digests;
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
import com.commafeed.backend.dao.UnitOfWork;
|
||||
import com.commafeed.backend.feed.parser.FeedParserResult.Content;
|
||||
@@ -25,7 +23,6 @@ import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.backend.service.FeedEntryService;
|
||||
import com.commafeed.backend.service.FeedService;
|
||||
import com.commafeed.frontend.ws.WebSocketMessageBuilder;
|
||||
@@ -47,29 +44,23 @@ public class FeedRefreshUpdater {
|
||||
private final FeedService feedService;
|
||||
private final FeedEntryService feedEntryService;
|
||||
private final FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
private final CacheService cache;
|
||||
private final WebSocketSessions webSocketSessions;
|
||||
|
||||
private final Striped<Lock> locks;
|
||||
|
||||
private final Meter entryCacheMiss;
|
||||
private final Meter entryCacheHit;
|
||||
private final Meter feedUpdated;
|
||||
private final Meter entryInserted;
|
||||
|
||||
public FeedRefreshUpdater(UnitOfWork unitOfWork, FeedService feedService, FeedEntryService feedEntryService, MetricRegistry metrics,
|
||||
FeedSubscriptionDAO feedSubscriptionDAO, CacheService cache, WebSocketSessions webSocketSessions) {
|
||||
FeedSubscriptionDAO feedSubscriptionDAO, WebSocketSessions webSocketSessions) {
|
||||
this.unitOfWork = unitOfWork;
|
||||
this.feedService = feedService;
|
||||
this.feedEntryService = feedEntryService;
|
||||
this.feedSubscriptionDAO = feedSubscriptionDAO;
|
||||
this.cache = cache;
|
||||
this.webSocketSessions = webSocketSessions;
|
||||
|
||||
locks = Striped.lazyWeakLock(100000);
|
||||
|
||||
entryCacheMiss = metrics.meter(MetricRegistry.name(getClass(), "entryCacheMiss"));
|
||||
entryCacheHit = metrics.meter(MetricRegistry.name(getClass(), "entryCacheHit"));
|
||||
feedUpdated = metrics.meter(MetricRegistry.name(getClass(), "feedUpdated"));
|
||||
entryInserted = metrics.meter(MetricRegistry.name(getClass(), "entryInserted"));
|
||||
}
|
||||
@@ -139,39 +130,21 @@ public class FeedRefreshUpdater {
|
||||
Map<FeedSubscription, Long> unreadCountBySubscription = new HashMap<>();
|
||||
|
||||
if (!entries.isEmpty()) {
|
||||
Set<String> lastEntries = cache.getLastEntries(feed);
|
||||
List<String> currentEntries = new ArrayList<>();
|
||||
|
||||
List<FeedSubscription> subscriptions = null;
|
||||
for (Entry entry : entries) {
|
||||
String cacheKey = cache.buildUniqueEntryKey(entry);
|
||||
if (!lastEntries.contains(cacheKey)) {
|
||||
log.debug("cache miss for {}", entry.url());
|
||||
if (subscriptions == null) {
|
||||
subscriptions = unitOfWork.call(() -> feedSubscriptionDAO.findByFeed(feed));
|
||||
}
|
||||
AddEntryResult addEntryResult = addEntry(feed, entry, subscriptions);
|
||||
processed &= addEntryResult.processed;
|
||||
inserted += addEntryResult.inserted ? 1 : 0;
|
||||
addEntryResult.subscriptionsForWhichEntryIsUnread.forEach(sub -> unreadCountBySubscription.merge(sub, 1L, Long::sum));
|
||||
|
||||
entryCacheMiss.mark();
|
||||
} else {
|
||||
log.debug("cache hit for {}", entry.url());
|
||||
entryCacheHit.mark();
|
||||
if (subscriptions == null) {
|
||||
subscriptions = unitOfWork.call(() -> feedSubscriptionDAO.findByFeed(feed));
|
||||
}
|
||||
|
||||
currentEntries.add(cacheKey);
|
||||
AddEntryResult addEntryResult = addEntry(feed, entry, subscriptions);
|
||||
processed &= addEntryResult.processed;
|
||||
inserted += addEntryResult.inserted ? 1 : 0;
|
||||
addEntryResult.subscriptionsForWhichEntryIsUnread.forEach(sub -> unreadCountBySubscription.merge(sub, 1L, Long::sum));
|
||||
}
|
||||
cache.setLastEntries(feed, currentEntries);
|
||||
|
||||
if (subscriptions == null) {
|
||||
if (inserted == 0) {
|
||||
feed.setMessage("No new entries found");
|
||||
} else if (inserted > 0) {
|
||||
log.debug("inserted {} entries for feed {}", inserted, feed.getId());
|
||||
List<User> users = subscriptions.stream().map(FeedSubscription::getUser).toList();
|
||||
cache.invalidateUnreadCount(subscriptions.toArray(new FeedSubscription[0]));
|
||||
cache.invalidateUserRootCategory(users.toArray(new User[0]));
|
||||
feed.setMessage("Found %s new entries".formatted(inserted));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.util.List;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedCategoryDAO;
|
||||
import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
@@ -28,7 +27,6 @@ public class OPMLImporter {
|
||||
|
||||
private final FeedCategoryDAO feedCategoryDAO;
|
||||
private final FeedSubscriptionService feedSubscriptionService;
|
||||
private final CacheService cache;
|
||||
|
||||
public void importOpml(User user, String xml) throws IllegalArgumentException, FeedException {
|
||||
xml = xml.substring(xml.indexOf('<'));
|
||||
@@ -79,6 +77,5 @@ public class OPMLImporter {
|
||||
log.error("error while importing {}: {}", outline.getXmlUrl(), e.getMessage());
|
||||
}
|
||||
}
|
||||
cache.invalidateUserRootCategory(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
import com.commafeed.backend.Digests;
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedEntryDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
@@ -32,7 +31,6 @@ public class FeedEntryService {
|
||||
private final FeedEntryStatusDAO feedEntryStatusDAO;
|
||||
private final FeedEntryContentService feedEntryContentService;
|
||||
private final FeedEntryFilteringService feedEntryFilteringService;
|
||||
private final CacheService cache;
|
||||
|
||||
public FeedEntry find(Feed feed, Entry entry) {
|
||||
String guidHash = Digests.sha1Hex(entry.guid());
|
||||
@@ -85,8 +83,6 @@ public class FeedEntryService {
|
||||
if (status.isMarkable()) {
|
||||
status.setRead(read);
|
||||
feedEntryStatusDAO.saveOrUpdate(status);
|
||||
cache.invalidateUnreadCount(sub);
|
||||
cache.invalidateUserRootCategory(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,8 +108,6 @@ public class FeedEntryService {
|
||||
List<FeedEntryStatus> statuses = feedEntryStatusDAO.findBySubscriptions(user, subscriptions, true, keywords, null, -1, -1, null,
|
||||
false, null, null, null);
|
||||
markList(statuses, olderThan, insertedBefore);
|
||||
cache.invalidateUnreadCount(subscriptions.toArray(new FeedSubscription[0]));
|
||||
cache.invalidateUserRootCategory(user);
|
||||
}
|
||||
|
||||
public void markStarredEntries(User user, Instant olderThan, Instant insertedBefore) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import java.util.stream.Collectors;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.commafeed.CommaFeedConfiguration;
|
||||
import com.commafeed.backend.cache.CacheService;
|
||||
import com.commafeed.backend.dao.FeedDAO;
|
||||
import com.commafeed.backend.dao.FeedEntryStatusDAO;
|
||||
import com.commafeed.backend.dao.FeedSubscriptionDAO;
|
||||
@@ -17,7 +16,6 @@ import com.commafeed.backend.feed.FeedUtils;
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedSubscription;
|
||||
import com.commafeed.backend.model.Models;
|
||||
import com.commafeed.backend.model.User;
|
||||
import com.commafeed.frontend.model.UnreadCount;
|
||||
|
||||
@@ -33,17 +31,15 @@ public class FeedSubscriptionService {
|
||||
private final FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
private final FeedService feedService;
|
||||
private final FeedRefreshEngine feedRefreshEngine;
|
||||
private final CacheService cache;
|
||||
private final CommaFeedConfiguration config;
|
||||
|
||||
public FeedSubscriptionService(FeedDAO feedDAO, FeedEntryStatusDAO feedEntryStatusDAO, FeedSubscriptionDAO feedSubscriptionDAO,
|
||||
FeedService feedService, FeedRefreshEngine feedRefreshEngine, CacheService cache, CommaFeedConfiguration config) {
|
||||
FeedService feedService, FeedRefreshEngine feedRefreshEngine, CommaFeedConfiguration config) {
|
||||
this.feedDAO = feedDAO;
|
||||
this.feedEntryStatusDAO = feedEntryStatusDAO;
|
||||
this.feedSubscriptionDAO = feedSubscriptionDAO;
|
||||
this.feedService = feedService;
|
||||
this.feedRefreshEngine = feedRefreshEngine;
|
||||
this.cache = cache;
|
||||
this.config = config;
|
||||
|
||||
// automatically refresh feeds after they are subscribed to
|
||||
@@ -95,7 +91,6 @@ public class FeedSubscriptionService {
|
||||
sub.setTitle(FeedUtils.truncate(title, 128));
|
||||
feedSubscriptionDAO.saveOrUpdate(sub);
|
||||
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return sub.getId();
|
||||
}
|
||||
|
||||
@@ -103,7 +98,6 @@ public class FeedSubscriptionService {
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, subId);
|
||||
if (sub != null) {
|
||||
feedSubscriptionDAO.delete(sub);
|
||||
cache.invalidateUserRootCategory(user);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -130,17 +124,9 @@ public class FeedSubscriptionService {
|
||||
}
|
||||
|
||||
public Map<Long, UnreadCount> getUnreadCount(User user) {
|
||||
return feedSubscriptionDAO.findAll(user).stream().collect(Collectors.toMap(FeedSubscription::getId, this::getUnreadCount));
|
||||
}
|
||||
|
||||
private UnreadCount getUnreadCount(FeedSubscription sub) {
|
||||
UnreadCount count = cache.getUnreadCount(sub);
|
||||
if (count == null) {
|
||||
log.debug("unread count cache miss for {}", Models.getId(sub));
|
||||
count = feedEntryStatusDAO.getUnreadCount(sub);
|
||||
cache.setUnreadCount(sub, count);
|
||||
}
|
||||
return count;
|
||||
return feedSubscriptionDAO.findAll(user)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(FeedSubscription::getId, feedEntryStatusDAO::getUnreadCount));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
|
||||
Reference in New Issue
Block a user