Compare commits
2 Commits
b51e119bcc
...
3b8a8f87e2
| Author | SHA1 | Date | |
|---|---|---|---|
| 3b8a8f87e2 | |||
| 424b8e28b2 |
@ -27,6 +27,20 @@ public class MangaIngestService {
|
|||||||
log.info(
|
log.info(
|
||||||
"Ingesting manga with mangaTitle '{}' from provider {}", mangaTitle, contentProviderId);
|
"Ingesting manga with mangaTitle '{}' from provider {}", mangaTitle, contentProviderId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
doIngestManga(contentProviderId, mangaTitle, url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(
|
||||||
|
"Unexpected error ingesting manga '{}' from provider {} at url '{}'",
|
||||||
|
mangaTitle,
|
||||||
|
contentProviderId,
|
||||||
|
url,
|
||||||
|
e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doIngestManga(long contentProviderId, String mangaTitle, String url) {
|
||||||
if (mangaContentProviderRepository.existsByMangaTitleIgnoreCaseAndContentProvider_Id(
|
if (mangaContentProviderRepository.existsByMangaTitleIgnoreCaseAndContentProvider_Id(
|
||||||
mangaTitle, contentProviderId)) {
|
mangaTitle, contentProviderId)) {
|
||||||
log.info(
|
log.info(
|
||||||
@ -51,6 +65,17 @@ public class MangaIngestService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mangaContentProviderRepository
|
||||||
|
.findByManga_IdAndContentProvider_Id(manga.getId(), contentProviderId)
|
||||||
|
.isPresent()) {
|
||||||
|
log.info(
|
||||||
|
"MangaContentProvider already exists for manga '{}' (ID: {}) and provider '{}', skipping ingest",
|
||||||
|
manga.getTitle(),
|
||||||
|
manga.getId(),
|
||||||
|
contentProviderId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var contentProvider = contentProviderService.find(contentProviderId);
|
var contentProvider = contentProviderService.find(contentProviderId);
|
||||||
|
|
||||||
@ -63,10 +88,11 @@ public class MangaIngestService {
|
|||||||
.build());
|
.build());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error(
|
log.error(
|
||||||
"Failed to ingest manga with mangaTitle '{}' from provider '{}'",
|
"Failed to save manga content provider for manga '{}' from provider '{}'",
|
||||||
mangaTitle,
|
mangaTitle,
|
||||||
contentProviderId,
|
contentProviderId,
|
||||||
e);
|
e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info(
|
log.info(
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
package com.magamochi.catalog.service;
|
package com.magamochi.catalog.service;
|
||||||
|
|
||||||
|
import static java.util.Objects.isNull;
|
||||||
import static java.util.Objects.nonNull;
|
import static java.util.Objects.nonNull;
|
||||||
|
|
||||||
import com.magamochi.catalog.model.entity.Manga;
|
import com.magamochi.catalog.model.entity.Manga;
|
||||||
@ -9,6 +10,7 @@ import com.magamochi.catalog.queue.producer.MangaUpdateProducer;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
@ -116,21 +118,21 @@ public class MangaResolutionService {
|
|||||||
if (nonNull(aniListId)) {
|
if (nonNull(aniListId)) {
|
||||||
var existingByAniList = mangaRepository.findByAniListId(aniListId);
|
var existingByAniList = mangaRepository.findByAniListId(aniListId);
|
||||||
if (existingByAniList.isPresent()) {
|
if (existingByAniList.isPresent()) {
|
||||||
return existingByAniList.get();
|
return mergeExternalIds(existingByAniList.get(), canonicalTitle, aniListId, malId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonNull(malId)) {
|
if (nonNull(malId)) {
|
||||||
var existingByMalId = mangaRepository.findByMalId(malId);
|
var existingByMalId = mangaRepository.findByMalId(malId);
|
||||||
if (existingByMalId.isPresent()) {
|
if (existingByMalId.isPresent()) {
|
||||||
return existingByMalId.get();
|
return mergeExternalIds(existingByMalId.get(), canonicalTitle, aniListId, malId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonNull(canonicalTitle)) {
|
if (nonNull(canonicalTitle)) {
|
||||||
var existingByTitle = mangaRepository.findByTitleIgnoreCase(canonicalTitle);
|
var existingByTitle = mangaRepository.findByTitleIgnoreCase(canonicalTitle);
|
||||||
if (existingByTitle.isPresent()) {
|
if (existingByTitle.isPresent()) {
|
||||||
return existingByTitle.get();
|
return mergeExternalIds(existingByTitle.get(), canonicalTitle, aniListId, malId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,13 +140,75 @@ public class MangaResolutionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Manga createAndNotifyManga(String title, Long aniListId, Long malId) {
|
private Manga createAndNotifyManga(String title, Long aniListId, Long malId) {
|
||||||
var manga =
|
try {
|
||||||
mangaRepository.save(
|
var manga =
|
||||||
Manga.builder().title(title).aniListId(aniListId).malId(malId).build());
|
mangaRepository.save(
|
||||||
|
Manga.builder().title(title).aniListId(aniListId).malId(malId).build());
|
||||||
|
|
||||||
mangaUpdateProducer.sendMangaUpdateCommand(new MangaUpdateCommand(manga.getId()));
|
try {
|
||||||
|
mangaUpdateProducer.sendMangaUpdateCommand(new MangaUpdateCommand(manga.getId()));
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to send manga update command for manga '{}' (ID: {})", title, manga.getId(), e);
|
||||||
|
}
|
||||||
|
|
||||||
return manga;
|
return manga;
|
||||||
|
} catch (DataIntegrityViolationException e) {
|
||||||
|
log.warn(
|
||||||
|
"Race condition while creating manga '{}' (aniListId={}, malId={}), re-querying existing",
|
||||||
|
title,
|
||||||
|
aniListId,
|
||||||
|
malId);
|
||||||
|
|
||||||
|
if (nonNull(aniListId)) {
|
||||||
|
var existing = mangaRepository.findByAniListId(aniListId);
|
||||||
|
if (existing.isPresent()) {
|
||||||
|
return mergeExternalIds(existing.get(), title, aniListId, malId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nonNull(malId)) {
|
||||||
|
var existing = mangaRepository.findByMalId(malId);
|
||||||
|
if (existing.isPresent()) {
|
||||||
|
return mergeExternalIds(existing.get(), title, aniListId, malId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nonNull(title)) {
|
||||||
|
var existing = mangaRepository.findByTitleIgnoreCase(title);
|
||||||
|
if (existing.isPresent()) {
|
||||||
|
return mergeExternalIds(existing.get(), title, aniListId, malId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Manga mergeExternalIds(Manga existing, String canonicalTitle, Long aniListId, Long malId) {
|
||||||
|
boolean updated = false;
|
||||||
|
|
||||||
|
if (isNull(existing.getAniListId()) && nonNull(aniListId)) {
|
||||||
|
existing.setAniListId(aniListId);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (isNull(existing.getMalId()) && nonNull(malId)) {
|
||||||
|
existing.setMalId(malId);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
if (isNull(existing.getTitle()) && nonNull(canonicalTitle)) {
|
||||||
|
existing.setTitle(canonicalTitle);
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updated) {
|
||||||
|
log.info(
|
||||||
|
"Merged external IDs into manga '{}' (ID: {}): aniListId={}, malId={}",
|
||||||
|
existing.getTitle(),
|
||||||
|
existing.getId(),
|
||||||
|
existing.getAniListId(),
|
||||||
|
existing.getMalId());
|
||||||
|
return mangaRepository.save(existing);
|
||||||
|
}
|
||||||
|
|
||||||
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
||||||
private record ProviderResult(String title, Long externalId) {}
|
private record ProviderResult(String title, Long externalId) {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user