Skip to content

Commit

Permalink
In the cleanup task, remove also the "broken" tracks which refer to n…
Browse files Browse the repository at this point in the history
…on-existing album or artist

- This kind of tracks may result from unlucky timing if the periodic cleanup task is run in the background while the scanning is in progress, as explained in one of the comments of #588
- After a77b15a, this kind of broken tracks have been skipped when creating collection.json. Before that commit, the broken tracks broke the app altogether.
- Removing the broken tracks enables fixing the collection by rescanning. The next time the app UI is loaded, the popup tells that there are new tracks to scan.
  • Loading branch information
paulijar committed Dec 2, 2017
1 parent 31c6a71 commit 99f1866
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 21 deletions.
2 changes: 1 addition & 1 deletion backgroundjob/cleanup.php
Expand Up @@ -17,7 +17,7 @@
class CleanUp {

/**
* Calls the cleanup method of the scanner
* Run background cleanup task
*/
public static function run() {
$app = new Music();
Expand Down
80 changes: 60 additions & 20 deletions db/maintenance.php
Expand Up @@ -31,6 +31,9 @@ public function __construct(IDBConnection $db, Logger $logger){
$this->logger = $logger;
}

/**
* Remove cover_file_id from album if the corresponding file does not exist
*/
private function removeObsoleteCoverImages() {
return $this->db->executeUpdate(
'UPDATE `*PREFIX*music_albums` SET `cover_file_id` = NULL
Expand All @@ -45,33 +48,67 @@ private function removeObsoleteCoverImages() {
);
}

private function removeObsoleteTracks() {
/**
* Remove all such rows from $tgtTable which don't have corresponding rows in $refTable
* so that $tgtTableKey = $refTableKey.
* @param string $tgtTable
* @param string $refTable
* @param string $tgtTableKey
* @param string $refTableKey
* @return Number of removed rows
*/
private function removeUnreferencedDbRows($tgtTable, $refTable, $tgtTableKey, $refTableKey) {
$tgtTable = '*PREFIX*' . $tgtTable;
$refTable = '*PREFIX*' . $refTable;

return $this->db->executeUpdate(
'DELETE FROM `*PREFIX*music_tracks` WHERE `file_id` IN (
SELECT `file_id` FROM (
SELECT `file_id` FROM `*PREFIX*music_tracks`
LEFT JOIN `*PREFIX*filecache`
ON `file_id`=`fileid`
WHERE `fileid` IS NULL
"DELETE FROM `$tgtTable` WHERE `id` IN (
SELECT `id` FROM (
SELECT `$tgtTable`.`id`
FROM `$tgtTable` LEFT JOIN `$refTable`
ON `$tgtTable`.`$tgtTableKey` = `$refTable`.`$refTableKey`
WHERE `$refTable`.`$refTableKey` IS NULL
) mysqlhack
)'
)"
);
}

/**
* Remvoe tracks which do not have corresponding file in the file system
* @return Number of removed tracks
*/
private function removeObsoleteTracks() {
return $this->removeUnreferencedDbRows('music_tracks', 'filecache', 'file_id', 'fileid');
}

/**
* Remove tracks which belong to non-existing album
* @return Number of removed tracks
*/
private function removeTracksWithNoAlbum() {
return $this->removeUnreferencedDbRows('music_tracks', 'music_albums', 'album_id', 'id');
}

/**
* Remove tracks which are performed by non-existing artist
* @return Number of removed tracks
*/
private function removeTracksWithNoArtist() {
return $this->removeUnreferencedDbRows('music_tracks', 'music_artists', 'artist_id', 'id');
}

/**
* Remove albums which have no tracks
* @return Number of removed albums
*/
private function removeObsoleteAlbums() {
return $this->db->executeUpdate(
'DELETE FROM `*PREFIX*music_albums` WHERE `id` IN (
SELECT `id` FROM (
SELECT `*PREFIX*music_albums`.`id`
FROM `*PREFIX*music_albums`
LEFT JOIN `*PREFIX*music_tracks`
ON `*PREFIX*music_tracks`.`album_id` = `*PREFIX*music_albums`.`id`
WHERE `*PREFIX*music_tracks`.`album_id` IS NULL
) as tmp
)'
);
return $this->removeUnreferencedDbRows('music_albums', 'music_tracks', 'id', 'album_id');
}

/**
* Remove artists which have no albums and no tracks
* @return Number of removed artists
*/
private function removeObsoleteArtists() {
return $this->db->executeUpdate(
'DELETE FROM `*PREFIX*music_artists` WHERE `id` NOT IN (
Expand All @@ -84,11 +121,14 @@ private function removeObsoleteArtists() {

/**
* Removes orphaned data from the database
* @return array describing the number of removed entries per type
*/
public function cleanUp() {
return [
'covers' => $this->removeObsoleteCoverImages(),
'tracks' => $this->removeObsoleteTracks(),
'tracks' => $this->removeObsoleteTracks()
+ $this->removeTracksWithNoAlbum()
+ $this->removeTracksWithNoArtist(),
'albums' => $this->removeObsoleteAlbums(),
'artists' => $this->removeObsoleteArtists()
];
Expand Down

0 comments on commit 99f1866

Please sign in to comment.