Make watched titles full recompute sources, not just a scoring weight
Build and Deploy / build-and-deploy (push) Successful in 2m14s
Build and Deploy / build-and-deploy (push) Successful in 2m14s
The original design ("Rework source model: library membership drives
sources, watched is a weight only") meant marking something "Уже
смотрел" without owning it never seeded its own TMDB/Kinopoisk
discoveries at all - it only ever showed up as a candidate itself, or
boosted OTHER sources' weight if it happened to already be a source
via ownership. That contradicts the actual intent behind watched
tracking: it should build the recommendation graph, not just softly
exclude a title from Рекомендации. Sources are now IN_LIBRARY ∪
REMOVED ∪ every WatchSignal.watched=true title regardless of status.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
e2caeab70f
commit
2188458646
@@ -12,13 +12,17 @@ import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Core recommendation pipeline:
|
||||
* 1. Sources = everything ever added to Radarr/Sonarr - still present
|
||||
* (IN_LIBRARY) or since removed (REMOVED). Being watched never gates
|
||||
* source membership, it only boosts a source's scoring weight.
|
||||
* 1. Sources = everything ever added to Radarr/Sonarr (still present or
|
||||
* since removed) UNION everything ever marked "Уже смотрел" - watching
|
||||
* something is itself a signal worth building the recommendation graph
|
||||
* from, not just a weight applied to sources that happen to already
|
||||
* qualify some other way (a watched title that was never owned would
|
||||
* otherwise never seed its own discoveries at all).
|
||||
* 2. For each source, call TMDB recommendations + similar and record
|
||||
* Intersection rows for whatever comes back.
|
||||
* 3. Separately, Kinopoisk's own "similar films" list is consulted as a
|
||||
@@ -44,6 +48,7 @@ public class RecomputeService {
|
||||
private final MediaService mediaService;
|
||||
private final MediaEntityRepository mediaRepository;
|
||||
private final IntersectionRepository intersectionRepository;
|
||||
private final WatchSignalRepository watchSignalRepository;
|
||||
private final ScoringConfigService scoringConfigService;
|
||||
private final IntegrationSettingService integrationSettingService;
|
||||
|
||||
@@ -66,6 +71,7 @@ public class RecomputeService {
|
||||
KinopoiskClient kinopoiskClient, MediaService mediaService,
|
||||
MediaEntityRepository mediaRepository,
|
||||
IntersectionRepository intersectionRepository,
|
||||
WatchSignalRepository watchSignalRepository,
|
||||
ScoringConfigService scoringConfigService,
|
||||
IntegrationSettingService integrationSettingService) {
|
||||
this.radarrClient = radarrClient;
|
||||
@@ -75,6 +81,7 @@ public class RecomputeService {
|
||||
this.mediaService = mediaService;
|
||||
this.mediaRepository = mediaRepository;
|
||||
this.intersectionRepository = intersectionRepository;
|
||||
this.watchSignalRepository = watchSignalRepository;
|
||||
this.scoringConfigService = scoringConfigService;
|
||||
this.integrationSettingService = integrationSettingService;
|
||||
}
|
||||
@@ -94,12 +101,17 @@ public class RecomputeService {
|
||||
private void doRecompute() {
|
||||
syncLibraries();
|
||||
|
||||
// Sources = everything ever added to Radarr/Sonarr, whether still
|
||||
// present (IN_LIBRARY) or since removed (REMOVED) - being watched is
|
||||
// a scoring weight boost only (see ScoringService), never a
|
||||
// membership requirement.
|
||||
// Sources = everything ever added to Radarr/Sonarr (still present or
|
||||
// since removed) UNION everything ever marked watched, regardless of
|
||||
// status - see the class Javadoc for why watched-but-never-owned
|
||||
// titles need to be full sources, not just a weight on other sources.
|
||||
Set<MediaEntity> sources = new LinkedHashSet<>(
|
||||
mediaRepository.findByStatusIn(List.of(MediaStatus.IN_LIBRARY, MediaStatus.REMOVED)));
|
||||
Set<Long> watchedIds = watchSignalRepository.findByWatchedTrue().stream()
|
||||
.map(WatchSignal::getMediaEntityId).collect(Collectors.toSet());
|
||||
if (!watchedIds.isEmpty()) {
|
||||
sources.addAll(mediaRepository.findAllById(watchedIds));
|
||||
}
|
||||
List<MediaEntity> kinopoiskCandidates = computeKinopoiskCandidates(sources);
|
||||
// Both phases count towards the same progress bar - computing the
|
||||
// Kinopoisk candidate list upfront (instead of only once its phase
|
||||
|
||||
Reference in New Issue
Block a user