ContentHeaderRepository.java
package net.sasasin.sreader.repository;
import static net.sasasin.sreader.jooq.Tables.CONTENT_FULL_TEXT;
import static net.sasasin.sreader.jooq.Tables.CONTENT_HEADER;
import static net.sasasin.sreader.jooq.Tables.FEED_URL;
import java.time.OffsetDateTime;
import java.util.List;
import net.sasasin.sreader.domain.ContentHeader;
import net.sasasin.sreader.domain.FullTextMethod;
import net.sasasin.sreader.domain.PendingFullTextTarget;
import net.sasasin.sreader.service.feed.ingestion.ContentHeaderUpsertOutcome;
import org.jooq.DSLContext;
import org.jooq.Record;
import org.springframework.stereotype.Repository;
@Repository
public class ContentHeaderRepository {
private final DSLContext dsl;
public ContentHeaderRepository(DSLContext dsl) {
this.dsl = dsl;
}
public ContentHeaderUpsertOutcome insertOrRefreshFetchUrl(ContentHeader header) {
OffsetDateTime now = OffsetDateTime.now();
boolean inserted =
dsl.insertInto(CONTENT_HEADER)
.set(CONTENT_HEADER.ID, header.id())
.set(CONTENT_HEADER.FEED_URL_ID, header.feedUrlId())
.set(CONTENT_HEADER.SOURCE_URL, header.sourceUrl())
.set(CONTENT_HEADER.FETCH_URL, header.fetchUrl())
.set(CONTENT_HEADER.CANONICAL_URL, header.canonicalUrl())
.set(CONTENT_HEADER.TITLE, header.title())
.set(CONTENT_HEADER.PUBLISHED_AT, header.publishedAt())
.set(CONTENT_HEADER.FEED_TEXT, header.feedText())
.set(CONTENT_HEADER.CREATED_AT, now)
.set(CONTENT_HEADER.UPDATED_AT, now)
.onConflict(CONTENT_HEADER.CANONICAL_URL)
.doNothing()
.execute()
== 1;
if (!inserted) {
dsl.update(CONTENT_HEADER)
.set(CONTENT_HEADER.FETCH_URL, header.fetchUrl())
.set(CONTENT_HEADER.UPDATED_AT, now)
.where(CONTENT_HEADER.CANONICAL_URL.eq(header.canonicalUrl()))
.execute();
return ContentHeaderUpsertOutcome.EXISTING_REFRESHED;
}
return ContentHeaderUpsertOutcome.INSERTED;
}
public List<ContentHeader> findWithoutFullText(int limit) {
return dsl.select(
CONTENT_HEADER.ID,
CONTENT_HEADER.FEED_URL_ID,
CONTENT_HEADER.SOURCE_URL,
CONTENT_HEADER.FETCH_URL,
CONTENT_HEADER.CANONICAL_URL,
CONTENT_HEADER.TITLE,
CONTENT_HEADER.PUBLISHED_AT,
CONTENT_HEADER.FEED_TEXT)
.from(CONTENT_HEADER)
.leftJoin(CONTENT_FULL_TEXT)
.on(CONTENT_HEADER.ID.eq(CONTENT_FULL_TEXT.CONTENT_HEADER_ID))
.where(CONTENT_FULL_TEXT.ID.isNull())
.orderBy(CONTENT_HEADER.CREATED_AT.asc())
.limit(limit)
.fetch(this::mapContentHeader);
}
public List<PendingFullTextTarget> findWithoutFullTextForUrlExtraction(int limit) {
return dsl.select(
CONTENT_HEADER.ID,
CONTENT_HEADER.FEED_URL_ID,
CONTENT_HEADER.SOURCE_URL,
CONTENT_HEADER.FETCH_URL,
CONTENT_HEADER.CANONICAL_URL,
CONTENT_HEADER.TITLE,
CONTENT_HEADER.PUBLISHED_AT,
CONTENT_HEADER.FEED_TEXT,
FEED_URL.FULL_TEXT_METHOD)
.from(CONTENT_HEADER)
.join(FEED_URL)
.on(CONTENT_HEADER.FEED_URL_ID.eq(FEED_URL.ID))
.leftJoin(CONTENT_FULL_TEXT)
.on(CONTENT_HEADER.ID.eq(CONTENT_FULL_TEXT.CONTENT_HEADER_ID))
.where(CONTENT_FULL_TEXT.ID.isNull())
.orderBy(CONTENT_HEADER.CREATED_AT.asc())
.limit(limit)
.fetch(
record ->
new PendingFullTextTarget(
mapContentHeader(record),
toFullTextMethod(record.get(FEED_URL.FULL_TEXT_METHOD))));
}
private FullTextMethod toFullTextMethod(String value) {
return value == null ? FullTextMethod.defaultMethod() : FullTextMethod.fromValue(value);
}
private ContentHeader mapContentHeader(Record record) {
return new ContentHeader(
record.get(CONTENT_HEADER.ID),
record.get(CONTENT_HEADER.FEED_URL_ID),
record.get(CONTENT_HEADER.SOURCE_URL),
record.get(CONTENT_HEADER.FETCH_URL),
record.get(CONTENT_HEADER.CANONICAL_URL),
record.get(CONTENT_HEADER.TITLE),
record.get(CONTENT_HEADER.PUBLISHED_AT),
record.get(CONTENT_HEADER.FEED_TEXT));
}
}