forked from Archives/Athou_commafeed
use more records
This commit is contained in:
@@ -12,9 +12,6 @@ import com.commafeed.backend.model.QFeedEntry;
|
|||||||
import com.querydsl.core.Tuple;
|
import com.querydsl.core.Tuple;
|
||||||
import com.querydsl.core.types.dsl.NumberExpression;
|
import com.querydsl.core.types.dsl.NumberExpression;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||||
|
|
||||||
@@ -64,10 +61,6 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
|||||||
return delete(list);
|
return delete(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
public record FeedCapacity(Long id, Long capacity) {
|
||||||
@Getter
|
|
||||||
public static class FeedCapacity {
|
|
||||||
private Long id;
|
|
||||||
private Long capacity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,9 +129,9 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
|||||||
if (CollectionUtils.isNotEmpty(keywords)) {
|
if (CollectionUtils.isNotEmpty(keywords)) {
|
||||||
for (FeedEntryKeyword keyword : keywords) {
|
for (FeedEntryKeyword keyword : keywords) {
|
||||||
BooleanBuilder or = new BooleanBuilder();
|
BooleanBuilder or = new BooleanBuilder();
|
||||||
or.or(CONTENT.content.containsIgnoreCase(keyword.getKeyword()));
|
or.or(CONTENT.content.containsIgnoreCase(keyword.keyword()));
|
||||||
or.or(CONTENT.title.containsIgnoreCase(keyword.getKeyword()));
|
or.or(CONTENT.title.containsIgnoreCase(keyword.keyword()));
|
||||||
if (keyword.getMode() == Mode.EXCLUDE) {
|
if (keyword.mode() == Mode.EXCLUDE) {
|
||||||
or.not();
|
or.not();
|
||||||
}
|
}
|
||||||
query.where(or);
|
query.where(or);
|
||||||
|
|||||||
@@ -2,20 +2,13 @@ package com.commafeed.backend.favicon;
|
|||||||
|
|
||||||
import jakarta.ws.rs.core.MediaType;
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
@Getter
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class Favicon {
|
public record Favicon(byte[] icon, MediaType mediaType) {
|
||||||
|
|
||||||
private static final MediaType DEFAULT_MEDIA_TYPE = MediaType.valueOf("image/x-icon");
|
private static final MediaType DEFAULT_MEDIA_TYPE = MediaType.valueOf("image/x-icon");
|
||||||
|
|
||||||
private final byte[] icon;
|
|
||||||
private final MediaType mediaType;
|
|
||||||
|
|
||||||
public Favicon(byte[] icon, String contentType) {
|
public Favicon(byte[] icon, String contentType) {
|
||||||
this(icon, parseMediaType(contentType));
|
this(icon, parseMediaType(contentType));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,23 +5,15 @@ import java.util.List;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A keyword used in a search query
|
* A keyword used in a search query
|
||||||
*/
|
*/
|
||||||
@Getter
|
public record FeedEntryKeyword(String keyword, Mode mode) {
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class FeedEntryKeyword {
|
|
||||||
|
|
||||||
public enum Mode {
|
public enum Mode {
|
||||||
INCLUDE, EXCLUDE
|
INCLUDE, EXCLUDE
|
||||||
}
|
}
|
||||||
|
|
||||||
private final String keyword;
|
|
||||||
private final Mode mode;
|
|
||||||
|
|
||||||
public static List<FeedEntryKeyword> fromQueryString(String keywords) {
|
public static List<FeedEntryKeyword> fromQueryString(String keywords) {
|
||||||
List<FeedEntryKeyword> list = new ArrayList<>();
|
List<FeedEntryKeyword> list = new ArrayList<>();
|
||||||
if (keywords != null) {
|
if (keywords != null) {
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import com.commafeed.frontend.ws.WebSocketMessageBuilder;
|
|||||||
import com.commafeed.frontend.ws.WebSocketSessions;
|
import com.commafeed.frontend.ws.WebSocketSessions;
|
||||||
import com.google.common.util.concurrent.Striped;
|
import com.google.common.util.concurrent.Striped;
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -171,11 +170,7 @@ public class FeedRefreshUpdater {
|
|||||||
WebSocketMessageBuilder.newFeedEntries(sub, unreadCount)));
|
WebSocketMessageBuilder.newFeedEntries(sub, unreadCount)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
private record AddEntryResult(boolean processed, boolean inserted, Set<FeedSubscription> subscriptionsForWhichEntryIsUnread) {
|
||||||
private static class AddEntryResult {
|
|
||||||
private final boolean processed;
|
|
||||||
private final boolean inserted;
|
|
||||||
private final Set<FeedSubscription> subscriptionsForWhichEntryIsUnread;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,10 +92,10 @@ public class DatabaseCleaningService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (final FeedCapacity feed : feeds) {
|
for (final FeedCapacity feed : feeds) {
|
||||||
long remaining = feed.getCapacity() - maxFeedCapacity;
|
long remaining = feed.capacity() - maxFeedCapacity;
|
||||||
do {
|
do {
|
||||||
final long rem = remaining;
|
final long rem = remaining;
|
||||||
int deleted = unitOfWork.call(() -> feedEntryDAO.deleteOldEntries(feed.getId(), Math.min(batchSize, rem)));
|
int deleted = unitOfWork.call(() -> feedEntryDAO.deleteOldEntries(feed.id(), Math.min(batchSize, rem)));
|
||||||
entriesDeletedMeter.mark(deleted);
|
entriesDeletedMeter.mark(deleted);
|
||||||
total += deleted;
|
total += deleted;
|
||||||
remaining -= deleted;
|
remaining -= deleted;
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ public class FeedREST {
|
|||||||
|
|
||||||
Feed feed = subscription.getFeed();
|
Feed feed = subscription.getFeed();
|
||||||
Favicon icon = feedService.fetchFavicon(feed);
|
Favicon icon = feedService.fetchFavicon(feed);
|
||||||
return Response.ok(icon.getIcon(), icon.getMediaType()).build();
|
return Response.ok(icon.icon(), icon.mediaType()).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
|
|||||||
@@ -306,7 +306,7 @@ public class FeverREST {
|
|||||||
|
|
||||||
FeverFavicon f = new FeverFavicon();
|
FeverFavicon f = new FeverFavicon();
|
||||||
f.setId(s.getFeed().getId());
|
f.setId(s.getFeed().getId());
|
||||||
f.setData(String.format("data:%s;base64,%s", favicon.getMediaType(), Base64.getEncoder().encodeToString(favicon.getIcon())));
|
f.setData(String.format("data:%s;base64,%s", favicon.mediaType(), Base64.getEncoder().encodeToString(favicon.icon())));
|
||||||
return f;
|
return f;
|
||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ class FacebookFaviconFetcherTest {
|
|||||||
Favicon result = faviconFetcher.fetch(feed);
|
Favicon result = faviconFetcher.fetch(feed);
|
||||||
|
|
||||||
Assertions.assertNotNull(result);
|
Assertions.assertNotNull(result);
|
||||||
Assertions.assertEquals(iconBytes, result.getIcon());
|
Assertions.assertEquals(iconBytes, result.icon());
|
||||||
Assertions.assertTrue(result.getMediaType().isCompatible(MediaType.valueOf(contentType)));
|
Assertions.assertTrue(result.mediaType().isCompatible(MediaType.valueOf(contentType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -86,8 +86,8 @@ class YoutubeFaviconFetcherTest {
|
|||||||
Favicon result = faviconFetcher.fetch(feed);
|
Favicon result = faviconFetcher.fetch(feed);
|
||||||
|
|
||||||
Assertions.assertNotNull(result);
|
Assertions.assertNotNull(result);
|
||||||
Assertions.assertEquals(iconBytes, result.getIcon());
|
Assertions.assertEquals(iconBytes, result.icon());
|
||||||
Assertions.assertTrue(result.getMediaType().isCompatible(MediaType.valueOf(contentType)));
|
Assertions.assertTrue(result.mediaType().isCompatible(MediaType.valueOf(contentType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -114,8 +114,8 @@ class YoutubeFaviconFetcherTest {
|
|||||||
Favicon result = faviconFetcher.fetch(feed);
|
Favicon result = faviconFetcher.fetch(feed);
|
||||||
|
|
||||||
Assertions.assertNotNull(result);
|
Assertions.assertNotNull(result);
|
||||||
Assertions.assertEquals(iconBytes, result.getIcon());
|
Assertions.assertEquals(iconBytes, result.icon());
|
||||||
Assertions.assertTrue(result.getMediaType().isCompatible(MediaType.valueOf(contentType)));
|
Assertions.assertTrue(result.mediaType().isCompatible(MediaType.valueOf(contentType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -151,8 +151,8 @@ class YoutubeFaviconFetcherTest {
|
|||||||
Favicon result = faviconFetcher.fetch(feed);
|
Favicon result = faviconFetcher.fetch(feed);
|
||||||
|
|
||||||
Assertions.assertNotNull(result);
|
Assertions.assertNotNull(result);
|
||||||
Assertions.assertEquals(iconBytes, result.getIcon());
|
Assertions.assertEquals(iconBytes, result.icon());
|
||||||
Assertions.assertTrue(result.getMediaType().isCompatible(MediaType.valueOf(contentType)));
|
Assertions.assertTrue(result.mediaType().isCompatible(MediaType.valueOf(contentType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -108,12 +108,12 @@ class DatabaseCleaningServiceTest {
|
|||||||
@Test
|
@Test
|
||||||
void cleanEntriesForFeedsExceedingCapacityDeletesOldEntries() {
|
void cleanEntriesForFeedsExceedingCapacityDeletesOldEntries() {
|
||||||
FeedCapacity feed1 = Mockito.mock(FeedCapacity.class);
|
FeedCapacity feed1 = Mockito.mock(FeedCapacity.class);
|
||||||
Mockito.when(feed1.getId()).thenReturn(1L);
|
Mockito.when(feed1.id()).thenReturn(1L);
|
||||||
Mockito.when(feed1.getCapacity()).thenReturn(180L);
|
Mockito.when(feed1.capacity()).thenReturn(180L);
|
||||||
|
|
||||||
FeedCapacity feed2 = Mockito.mock(FeedCapacity.class);
|
FeedCapacity feed2 = Mockito.mock(FeedCapacity.class);
|
||||||
Mockito.when(feed2.getId()).thenReturn(2L);
|
Mockito.when(feed2.id()).thenReturn(2L);
|
||||||
Mockito.when(feed2.getCapacity()).thenReturn(120L);
|
Mockito.when(feed2.capacity()).thenReturn(120L);
|
||||||
|
|
||||||
Mockito.when(feedEntryDAO.findFeedsExceedingCapacity(50, BATCH_SIZE))
|
Mockito.when(feedEntryDAO.findFeedsExceedingCapacity(50, BATCH_SIZE))
|
||||||
.thenReturn(Arrays.asList(feed1, feed2))
|
.thenReturn(Arrays.asList(feed1, feed2))
|
||||||
|
|||||||
Reference in New Issue
Block a user