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));
  }
}