use of net.robinfriedli.aiode.entities.SpotifyRedirectIndex in project aiode by robinfriedli.
the class SpotifyRedirectService method redirectTrack.
public void redirectTrack(HollowYouTubeVideo youTubeVideo) throws IOException {
SpotifyTrack spotifyTrack = youTubeVideo.getRedirectedSpotifyTrack();
if (spotifyTrack == null) {
throw new IllegalArgumentException(youTubeVideo.toString() + " is not a placeholder for a redirected Spotify Track");
}
// early exit to avoid duplicate loading of Playables that have been loaded prioritised by invoking Playable#fetchNow
if (youTubeVideo.isDone()) {
return;
}
youTubeVideo.markLoading();
String spotifyTrackId = spotifyTrack.getId();
Optional<SpotifyRedirectIndex> persistedSpotifyRedirectIndex;
if (!Strings.isNullOrEmpty(spotifyTrackId)) {
persistedSpotifyRedirectIndex = queryExistingIndex(session, spotifyTrackId);
} else {
persistedSpotifyRedirectIndex = Optional.empty();
}
if (persistedSpotifyRedirectIndex.isPresent()) {
SpotifyRedirectIndex spotifyRedirectIndex = persistedSpotifyRedirectIndex.get();
YouTubeVideo video = youTubeService.getVideoForId(spotifyRedirectIndex.getYouTubeId());
if (video != null) {
try {
youTubeVideo.setId(video.getVideoId());
youTubeVideo.setDuration(video.getDuration());
} catch (UnavailableResourceException e) {
// never happens for YouTubeVideoImpl instances
throw new RuntimeException(e);
}
youTubeVideo.setTitle(spotifyTrack.getDisplay());
runUpdateTask(spotifyTrackId, (index, session) -> index.setLastUsed(LocalDate.now()));
return;
} else {
runUpdateTask(spotifyTrackId, (index, session) -> session.delete(index));
}
}
youTubeService.redirectSpotify(youTubeVideo);
if (!youTubeVideo.isCanceled() && !Strings.isNullOrEmpty(spotifyTrack.getId())) {
SINGE_THREAD_EXECUTOR_SERVICE.execute(() -> StaticSessionProvider.consumeSession(otherThreadSession -> {
try {
String videoId = youTubeVideo.getVideoId();
SpotifyRedirectIndex spotifyRedirectIndex = new SpotifyRedirectIndex(spotifyTrack.getId(), videoId, spotifyTrack.getKind(), otherThreadSession);
// check again if the index was not created by other thread
if (queryExistingIndex(otherThreadSession, spotifyTrackId).isEmpty()) {
invoker.invoke(() -> otherThreadSession.persist(spotifyRedirectIndex));
}
} catch (UnavailableResourceException e) {
logger.warn("Tried creating a SpotifyRedirectIndex for an unavailable Track");
} catch (Exception e) {
logger.error("Exception while creating SpotifyRedirectIndex", e);
}
}));
}
}
use of net.robinfriedli.aiode.entities.SpotifyRedirectIndex in project aiode by robinfriedli.
the class RefreshSpotifyRedirectIndicesTask method run.
@Override
protected void run(JobExecutionContext jobExecutionContext) {
logger.info("Starting SpotifyRedirectIndex refresh");
SessionFactory sessionFactory = StaticSessionProvider.getSessionFactory();
SpotifyRedirectIndexModificationLock spotifyRedirectIndexModificationLock = new SpotifyRedirectIndexModificationLock();
spotifyRedirectIndexModificationLock.setCreationTimeStamp(LocalDateTime.now());
try (Session session = sessionFactory.openSession()) {
Transaction transaction = session.beginTransaction();
session.persist(spotifyRedirectIndexModificationLock);
transaction.commit();
}
try {
Aiode aiode = Aiode.get();
Stopwatch stopwatch = Stopwatch.createStarted();
YouTubeService youTubeService = aiode.getAudioManager().getYouTubeService();
SpotifyTrackBulkLoadingService spotifyTrackBulkLoadingService = new SpotifyTrackBulkLoadingService(spotifyApi, true);
LocalDate currentDate = LocalDate.now();
LocalDate date4WeeksAgo = currentDate.minusDays(28);
StaticSessionProvider.consumeSession(session -> {
CriteriaBuilder cb = session.getCriteriaBuilder();
CriteriaQuery<SpotifyRedirectIndex> query = cb.createQuery(SpotifyRedirectIndex.class);
Root<SpotifyRedirectIndex> root = query.from(SpotifyRedirectIndex.class);
query.where(cb.lessThan(root.get("lastUpdated"), date4WeeksAgo));
query.orderBy(cb.asc(root.get("lastUpdated")));
List<SpotifyRedirectIndex> indices = session.createQuery(query).setLockOptions(new LockOptions(LockMode.PESSIMISTIC_WRITE)).getResultList();
if (indices.isEmpty()) {
return;
}
BigDecimal averageDailyIndices = (BigDecimal) session.createSQLQuery("select avg(count) from (select count(*) as count from spotify_redirect_index group by last_updated) as sub").uniqueResult();
int average = averageDailyIndices.setScale(0, RoundingMode.CEILING).intValue();
int updateCount = 0;
for (SpotifyRedirectIndex index : indices) {
SpotifyTrackKind kind = index.getSpotifyItemKind().asEnum();
RefreshTrackIndexTask task = new RefreshTrackIndexTask(session, index, youTubeService);
String spotifyId = index.getSpotifyId();
if (!Strings.isNullOrEmpty(spotifyId)) {
spotifyTrackBulkLoadingService.add(createItem(spotifyId, kind), task);
} else {
session.delete(index);
}
++updateCount;
if (updateCount == average) {
break;
}
}
spotifyTrackBulkLoadingService.perform();
stopwatch.stop();
logger.info(String.format("Regenerated %d spotify redirect indices in %d seconds", updateCount, stopwatch.elapsed(TimeUnit.SECONDS)));
});
} finally {
Transaction transaction = null;
try (Session session = sessionFactory.openSession()) {
transaction = session.beginTransaction();
// since hibernate is now bootstrapped by JPA rather than native after implementing spring boot
// the entity has the be merged because JPA does not allow the deletion of detached entities
Object merge = session.merge(spotifyRedirectIndexModificationLock);
session.delete(merge);
transaction.commit();
} catch (Throwable e) {
// catch exceptions thrown in the finally block so as to not override exceptions thrown in the try block
logger.error("Exception thrown while deleting SpotifyRedirectIndexModificationLock", e);
if (transaction != null) {
transaction.rollback();
}
}
}
}
Aggregations