FeedEntryImportService.java
package net.sasasin.sreader.service.feed.ingestion;
import com.rometools.rome.feed.synd.SyndEntry;
import java.net.URI;
import net.sasasin.sreader.domain.FeedUrl;
import org.springframework.stereotype.Service;
/** Feed-level orchestration; each entry's mapping and persistence is delegated. */
@Service
public class FeedEntryImportService {
private final FeedDocumentService feedDocumentService;
private final FeedEntryImporter entryImporter;
FeedEntryImportService(FeedDocumentService feedDocumentService, FeedEntryImporter entryImporter) {
this.feedDocumentService = feedDocumentService;
this.entryImporter = entryImporter;
}
public FeedImportResult importEntries(FeedUrl feedUrl) {
FeedDocumentOutcome document = feedDocumentService.fetch(URI.create(feedUrl.url()));
return switch (document) {
case FeedDocumentOutcome.Failed failed ->
new FeedImportResult.Failed(FeedImportSummary.empty(), failed.failure());
case FeedDocumentOutcome.Fetched fetched -> importFetchedEntries(feedUrl, fetched);
};
}
private FeedImportResult importFetchedEntries(
FeedUrl feedUrl, FeedDocumentOutcome.Fetched fetched) {
FeedImportSummary summary = FeedImportSummary.empty();
for (SyndEntry entry : fetched.entries()) {
FeedEntryImportOutcome outcome = entryImporter.importEntry(feedUrl, entry);
summary = summary.plusEntry(outcome);
if (outcome instanceof FeedEntryImportOutcome.Failed failed) {
// Preserve current feed-level abort semantics for fatal entry failures.
return new FeedImportResult.Failed(summary, failed.failure());
}
}
return new FeedImportResult.Completed(summary);
}
}