Further optimize the AutoDJ queue builder.

This commit is contained in:
Buster "Silver Eagle" Neece 2021-04-11 23:47:54 -05:00
parent e7cf4e585e
commit 9e0cddbb39
No known key found for this signature in database
GPG Key ID: 6D9E12FF03411F4E
3 changed files with 35 additions and 54 deletions

View File

@ -29,6 +29,11 @@ release channel, you can take advantage of these new features and fixes.
- Instances of the "Pause" icon across the system have been replaced with the "Stop" icon to more properly indicate what
they do.
- Heavy performance optimizations have been made in the following areas:
- Looping through, and processing, station media (5-minute sync)
- Processing listeners for stations with large listener counts
- The AutoDJ queue building process
## Bug Fixes
- Fixed a minor bug with the `is_now` parameter on the Schedule API endpoint.

View File

@ -101,36 +101,6 @@ class StationQueueRepository extends Repository
return $this->getUpcomingBaseQuery($station)->getQuery();
}
public function clearDuplicatesInQueue(Entity\Station $station): void
{
$upcomingQueue = $this->em->createQuery(
<<<'DQL'
SELECT sq.id, sq.song_id
FROM App\Entity\StationQueue sq
WHERE sq.station = :station
AND sq.sent_to_autodj = 0
ORDER BY sq.timestamp_cued ASC
DQL
)->setParameter('station', $station)
->getArrayResult();
$removeQueueItemQuery = $this->em->createQuery(
<<<'DQL'
DELETE FROM App\Entity\StationQueue sq WHERE sq.id = :id
DQL
);
$lastItem = null;
foreach ($upcomingQueue as $queue) {
if (null !== $lastItem && $lastItem === $queue['song_id']) {
$removeQueueItemQuery->setParameter('id', $queue['id'])->execute();
continue;
}
$lastItem = $queue['song_id'];
}
}
public function getNextInQueue(Entity\Station $station): ?Entity\StationQueue
{
return $this->getUpcomingBaseQuery($station)

View File

@ -142,35 +142,50 @@ class AutoDJ
$stationTz = $station->getTimezoneObject();
$upcomingQueue = $this->queueRepo->getUpcomingQueue($station);
$queueLength = count($upcomingQueue);
$lastSongId = null;
$queueLength = 0;
foreach ($upcomingQueue as $queueRow) {
// Prevent the exact same track from being played twice during this loop
if (null !== $lastSongId && $lastSongId === $queueRow->getSongId()) {
$this->em->remove($queueRow);
continue;
}
$queueLength++;
$lastSongId = $queueRow->getSongId();
$queueRow->setTimestampCued($now->getTimestamp());
$this->em->persist($queueRow);
$timestampCued = CarbonImmutable::createFromTimestamp($queueRow->getTimestampCued(), $stationTz);
$duration = $queueRow->getDuration() ?? 1;
$now = $this->getAdjustedNow($station, $timestampCued, $duration);
$now = $this->getAdjustedNow($station, $timestampCued, $queueRow->getDuration() ?? 1);
}
$this->em->flush();
$this->em->clear();
// Build the remainder of the queue.
while ($queueLength < $maxQueueLength) {
$station = $this->em->refetch($station);
$now = $this->cueNextSong($station, $now);
$queueLength++;
$queueRow = $this->cueNextSong($station, $now);
if ($queueRow instanceof Entity\StationQueue) {
$this->em->persist($queueRow);
// Prevent the exact same track from being played twice during this loop
if (null !== $lastSongId && $lastSongId === $queueRow->getSongId()) {
$this->em->remove($queueRow);
} else {
$lastSongId = $queueRow->getSongId();
$now = $this->getAdjustedNow($station, $now, $queueRow->getDuration() ?? 1);
}
} else {
break;
}
$this->em->flush();
$this->em->clear();
gc_collect_cycles();
$queueLength++;
}
$station = $this->em->refetch($station);
$this->queueRepo->clearDuplicatesInQueue($station);
$this->logger->popProcessor();
}
@ -204,7 +219,7 @@ class AutoDJ
return max($now, $adjustedNow);
}
protected function cueNextSong(Entity\Station $station, CarbonInterface $now): CarbonInterface
protected function cueNextSong(Entity\Station $station, CarbonInterface $now): ?Entity\StationQueue
{
$this->logger->debug(
'Adding to station queue.',
@ -224,18 +239,9 @@ class AutoDJ
$queueRow = $event->getNextSong();
if ($queueRow instanceof Entity\StationQueue) {
$mediaRow = $queueRow->getMedia();
if ($mediaRow instanceof Entity\StationMedia) {
$mediaRow->updateSongId();
$this->em->persist($mediaRow);
}
$queueRow->setLog($testHandler->getRecords());
$this->em->persist($queueRow);
$now = $this->getAdjustedNow($station, $now, $queueRow->getDuration());
}
return $now;
return $queueRow;
}
}