Skip to content
Snippets Groups Projects
Unverified Commit 0d161021 authored by FarbodZamani's avatar FarbodZamani Committed by GitHub
Browse files

Fix playlist sync db issue (#1366)

* Enhance playlist migration by enforcing foreign key constraints and ensuring non-nullable columns

* make sure the playlist table has no null config_id

* Draft: check for invalid records!

* add more error handling

* try different fkey name

* try separate db query for the same fkey
parent a48afda5
No related branches found
No related tags found
No related merge requests found
...@@ -19,17 +19,21 @@ class PlaylistMigration ...@@ -19,17 +19,21 @@ class PlaylistMigration
{ {
$db = DBManager::get(); $db = DBManager::get();
// Default opencast server if playlist belongs to no opencast server
$default_config_id = \Config::get()->OPENCAST_DEFAULT_SERVER;
try {
// Migrate existing playlists to Opencast // Migrate existing playlists to Opencast
$playlists = Playlists::findBySQL('service_playlist_id IS NULL'); $playlists = Playlists::findBySQL('service_playlist_id IS NULL');
// Try three times // Try three times
$tries = 0; $tries = 0;
while (!empty($playlists) && $tries < 3) { while (!empty($playlists) && $tries < 10) {
foreach ($playlists as $playlist) { foreach ($playlists as $playlist) {
$config_id = $playlist->config_id; $config_id = $playlist->config_id ?? null;
if (empty($config_id)) { if (empty($config_id)) {
// Default opencast server if playlist belongs to no opencast server // Default opencast server if playlist belongs to no opencast server
$config_id = \Config::get()->OPENCAST_DEFAULT_SERVER; $config_id = $default_config_id;
} }
// Get playlist videos // Get playlist videos
...@@ -67,12 +71,57 @@ class PlaylistMigration ...@@ -67,12 +71,57 @@ class PlaylistMigration
$tries++; $tries++;
} }
// What is the point of letting the process continue if there are still playlists with null service_playlist_id of duplicated service_playlist_ids?
$duplicate_service_playlist_ids = $db->query(
"SELECT service_playlist_id, COUNT(*) as count
FROM oc_playlist
WHERE service_playlist_id IS NOT NULL
GROUP BY service_playlist_id
HAVING count > 1"
)->fetchAll(\PDO::FETCH_ASSOC);
if (!empty($playlists) || !empty($duplicate_service_playlist_ids)) {
$message = "Migration failed due to invalid data records:\n";
if (!empty($playlists)) {
$message .= "Playlists with null service_playlist_id:\n";
foreach ($playlists as $playlist) {
$message .= "Playlist ID: {$playlist->id}\n";
}
}
if (!empty($duplicate_service_playlist_ids)) {
$message .= "Duplicate service_playlist_ids:\n";
foreach ($duplicate_service_playlist_ids as $record) {
$message .= "Service Playlist ID: {$record['service_playlist_id']}, Count: {$record['count']}\n";
}
}
throw new \Exception($message);
}
// We need another step to make sure config id is set and it is not null before altering the table with not-null config_id.
$null_config_playlists = Playlists::findBySQL('config_id IS NULL');
while (!empty($null_config_playlists)) {
foreach ($null_config_playlists as $null_config_playlist) {
// Store config id with default config id.
$null_config_playlist->config_id = $default_config_id;
$null_config_playlist->store();
}
$null_config_playlists = Playlists::findBySQL('config_id IS NULL');
}
// Forbid playlist without related oc playlist // Forbid playlist without related oc playlist
// First drop foreign key constraint
$db->exec('ALTER TABLE `oc_playlist` DROP FOREIGN KEY `oc_playlist_ibfk_1`');
// Then change column to not null
$db->exec('ALTER TABLE `oc_playlist` $db->exec('ALTER TABLE `oc_playlist`
CHANGE COLUMN `config_id` `config_id` int NOT NULL, CHANGE COLUMN `config_id` `config_id` int NOT NULL,
CHANGE COLUMN `service_playlist_id` `service_playlist_id` varchar(64) UNIQUE NOT NULL' CHANGE COLUMN `service_playlist_id` `service_playlist_id` varchar(64) UNIQUE NOT NULL'
); );
// Then add foreign key constraint again
$db->exec('ALTER TABLE `oc_playlist`
ADD FOREIGN KEY `oc_playlist_ibfk_1` (`config_id`) REFERENCES `oc_config` (`id`)
ON DELETE RESTRICT ON UPDATE RESTRICT'
);
// Forbid playlist video without related oc playlist entry // Forbid playlist video without related oc playlist entry
$db->exec('ALTER TABLE `oc_playlist_video` $db->exec('ALTER TABLE `oc_playlist_video`
CHANGE COLUMN `service_entry_id` `service_entry_id` int NOT NULL' CHANGE COLUMN `service_entry_id` `service_entry_id` int NOT NULL'
...@@ -93,6 +142,9 @@ class PlaylistMigration ...@@ -93,6 +142,9 @@ class PlaylistMigration
$scheduler->schedulePeriodic($task_id, -10); // negative value means "every x minutes" $scheduler->schedulePeriodic($task_id, -10); // negative value means "every x minutes"
\CronjobSchedule::findByTask_id($task_id)[0]->activate(); \CronjobSchedule::findByTask_id($task_id)[0]->activate();
} }
} catch (\Throwable $th) {
throw new \Exception('Migration fehlgeschlagen: ' . $th->getMessage());
}
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment