Ignore destination sources with found matches on search retry

This commit is contained in:
schroda
2026-05-16 21:57:44 +02:00
parent 8d90a91537
commit a15cd20031

View File

@@ -801,121 +801,125 @@ export class MigrationManager {
}); });
try { try {
const searchPromises = MigrationManager.getDestinationSourceIds(entry.sourceId).map((destSourceId) => const searchPromises = MigrationManager.getDestinationSourceIds(entry.sourceId)
MigrationManager.getParallelSourceQueue()(async () => { .filter((destSourceId) => !entry.destSourceIdToSearchState[destSourceId])
if (signal.aborted) { .map((destSourceId) =>
return null; MigrationManager.getParallelSourceQueue()(async () => {
} if (signal.aborted) {
return null;
}
if ( if (
!selectHighestChapterNumberSource && !selectHighestChapterNumberSource &&
MigrationManager.hasHigherSourcePriorityMatch(mangaId, destSourceId) MigrationManager.hasHigherSourcePriorityMatch(mangaId, destSourceId)
) { ) {
return null; return null;
} }
const foundMatches = await (async () => { const foundMatches = await (async () => {
try { try {
return await MigrationManager.findMatchesForMangaInSource( return await MigrationManager.findMatchesForMangaInSource(
mangaId, mangaId,
mangaTitle, mangaTitle,
destSourceId, destSourceId,
signal, signal,
options, options,
); );
} catch (e) { } catch (e) {
MigrationManager.updateState((draft) => {
const draftEntry = draft.entries[mangaId];
draftEntry.destSourceIdToSearchState[destSourceId] = false;
});
throw e;
}
})();
if (!foundMatches.length) {
MigrationManager.updateState((draft) => { MigrationManager.updateState((draft) => {
const draftEntry = draft.entries[mangaId]; const draftEntry = draft.entries[mangaId];
draftEntry.destSourceIdToSearchState[destSourceId] = false; draftEntry.destSourceIdToSearchState[destSourceId] = false;
}); });
throw e; return null;
} }
})();
if (!foundMatches.length) {
MigrationManager.updateState((draft) => { MigrationManager.updateState((draft) => {
const draftEntry = draft.entries[mangaId]; const draftEntry = draft.entries[mangaId];
const draftMatchEntry = draftEntry.selectedMatchMangaId
? draft.entries[draftEntry.selectedMatchMangaId]
: null;
draftEntry.destSourceIdToSearchState[destSourceId] = false; const matches = foundMatches.map((manga) => ({
id: manga.id,
title: manga.title,
artist: manga.artist,
author: manga.author,
latestChapterNumber: manga.highestNumberedChapter?.chapterNumber,
thumbnailUrl: manga.thumbnailUrl,
sourceId: manga.sourceId,
sourceTitle: manga.source?.displayName,
}));
draftEntry.destSourceIdToSearchState[destSourceId] = true;
draftEntry.searchMatches = [...draftEntry.searchMatches, ...matches];
const matchesByChapterNumber = Object.groupBy(
matches,
(match) => match.latestChapterNumber ?? -1,
);
const latestChapterNumber = Math.max(
...Object.keys(matchesByChapterNumber).map((chapterNumber) => Number(chapterNumber)),
);
const bestMatch = matchesByChapterNumber[latestChapterNumber]?.[0];
assertIsDefined(bestMatch);
const entryLatestChapterNumber = draftEntry.latestChapterNumber ?? Number.MIN_SAFE_INTEGER;
const selectedMatchLatestChapterNumber =
draftMatchEntry?.latestChapterNumber ?? Number.MIN_SAFE_INTEGER;
const hasNewerChapterVsEntry = latestChapterNumber > entryLatestChapterNumber;
const hasNewerChapterVsSelectedMatch =
latestChapterNumber > selectedMatchLatestChapterNumber;
const hasNewerChapter = hasNewerChapterVsEntry && hasNewerChapterVsSelectedMatch;
const hasSameLatestChapterAsSelectedMatch =
!!draftMatchEntry && selectedMatchLatestChapterNumber === latestChapterNumber;
const hasHigherSourcePriority = !MigrationManager.hasHigherSourcePriorityMatch(
mangaId,
destSourceId,
);
const ignoreOutdatedMatch = ignoreOutdatedMatches && !hasNewerChapter;
const isPreferredSourcePriorityMatch =
hasHigherSourcePriority && !selectHighestChapterNumberSource;
const isPreferredChapterNumberMatch =
selectHighestChapterNumberSource &&
(hasNewerChapter ||
(hasHigherSourcePriority && hasSameLatestChapterAsSelectedMatch) ||
!draftMatchEntry);
const isPreferredMatch =
!ignoreOutdatedMatch &&
(isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch);
if (isPreferredMatch) {
draftEntry.selectedMatchMangaId = bestMatch.id;
draftEntry.selectedMatchSourceId = destSourceId;
}
if (
!selectHighestChapterNumberSource &&
!MigrationManager.isHigherPrioritySourceUnsettled(mangaId, destSourceId)
) {
searchController.abort(`Found best match in source "${destSourceId}"`);
}
}); });
}),
return null; );
}
MigrationManager.updateState((draft) => {
const draftEntry = draft.entries[mangaId];
const draftMatchEntry = draftEntry.selectedMatchMangaId
? draft.entries[draftEntry.selectedMatchMangaId]
: null;
const matches = foundMatches.map((manga) => ({
id: manga.id,
title: manga.title,
artist: manga.artist,
author: manga.author,
latestChapterNumber: manga.highestNumberedChapter?.chapterNumber,
thumbnailUrl: manga.thumbnailUrl,
sourceId: manga.sourceId,
sourceTitle: manga.source?.displayName,
}));
draftEntry.destSourceIdToSearchState[destSourceId] = true;
draftEntry.searchMatches = [...draftEntry.searchMatches, ...matches];
const matchesByChapterNumber = Object.groupBy(
matches,
(match) => match.latestChapterNumber ?? -1,
);
const latestChapterNumber = Math.max(
...Object.keys(matchesByChapterNumber).map((chapterNumber) => Number(chapterNumber)),
);
const bestMatch = matchesByChapterNumber[latestChapterNumber]?.[0];
assertIsDefined(bestMatch);
const entryLatestChapterNumber = draftEntry.latestChapterNumber ?? Number.MIN_SAFE_INTEGER;
const selectedMatchLatestChapterNumber =
draftMatchEntry?.latestChapterNumber ?? Number.MIN_SAFE_INTEGER;
const hasNewerChapterVsEntry = latestChapterNumber > entryLatestChapterNumber;
const hasNewerChapterVsSelectedMatch = latestChapterNumber > selectedMatchLatestChapterNumber;
const hasNewerChapter = hasNewerChapterVsEntry && hasNewerChapterVsSelectedMatch;
const hasSameLatestChapterAsSelectedMatch =
!!draftMatchEntry && selectedMatchLatestChapterNumber === latestChapterNumber;
const hasHigherSourcePriority = !MigrationManager.hasHigherSourcePriorityMatch(
mangaId,
destSourceId,
);
const ignoreOutdatedMatch = ignoreOutdatedMatches && !hasNewerChapter;
const isPreferredSourcePriorityMatch =
hasHigherSourcePriority && !selectHighestChapterNumberSource;
const isPreferredChapterNumberMatch =
selectHighestChapterNumberSource &&
(hasNewerChapter ||
(hasHigherSourcePriority && hasSameLatestChapterAsSelectedMatch) ||
!draftMatchEntry);
const isPreferredMatch =
!ignoreOutdatedMatch && (isPreferredSourcePriorityMatch || isPreferredChapterNumberMatch);
if (isPreferredMatch) {
draftEntry.selectedMatchMangaId = bestMatch.id;
draftEntry.selectedMatchSourceId = destSourceId;
}
if (
!selectHighestChapterNumberSource &&
!MigrationManager.isHigherPrioritySourceUnsettled(mangaId, destSourceId)
) {
searchController.abort(`Found best match in source "${destSourceId}"`);
}
});
}),
);
const searchMatchPromises = await Promise.allSettled(searchPromises); const searchMatchPromises = await Promise.allSettled(searchPromises);