Prevent rating_key collisions when updating metadata

This commit is contained in:
JonnyWong16 2022-02-06 23:18:53 -08:00
parent cba746920a
commit c3d09d34f8
No known key found for this signature in database
GPG key ID: B1F1F9807184697A
3 changed files with 120 additions and 24 deletions

View file

@ -233,7 +233,8 @@ DOCUMENTATION :: END
data: { data: {
old_rating_key: '${query["rating_key"]}', old_rating_key: '${query["rating_key"]}',
new_rating_key: new_rating_key, new_rating_key: new_rating_key,
media_type: '${query["media_type"]}' media_type: '${query["media_type"]}',
single_update: true
}, },
async: true, async: true,
success: function (data) { success: function (data) {

View file

@ -44,6 +44,13 @@ else:
from plexpy import pmsconnect from plexpy import pmsconnect
from plexpy import session from plexpy import session
# Temporarily store update_metadata row ids in memory to prevent rating_key collisions
_UPDATE_METADATA_IDS = {
'grandparent_rating_key_ids': set(),
'parent_rating_key_ids': set(),
'rating_key_ids': set()
}
class DataFactory(object): class DataFactory(object):
""" """
@ -1831,7 +1838,7 @@ class DataFactory(object):
return key_list return key_list
def update_metadata(self, old_key_list='', new_key_list='', media_type=''): def update_metadata(self, old_key_list='', new_key_list='', media_type='', single_update=False):
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
@ -1853,6 +1860,15 @@ class DataFactory(object):
if mapping: if mapping:
logger.info("Tautulli DataFactory :: Updating metadata in the database.") logger.info("Tautulli DataFactory :: Updating metadata in the database.")
global _UPDATE_METADATA_IDS
if single_update:
_UPDATE_METADATA_IDS = {
'grandparent_rating_key_ids': set(),
'parent_rating_key_ids': set(),
'rating_key_ids': set()
}
for old_key, new_key in mapping.items(): for old_key, new_key in mapping.items():
metadata = pms_connect.get_metadata_details(new_key) metadata = pms_connect.get_metadata_details(new_key)
@ -1862,31 +1878,107 @@ class DataFactory(object):
if metadata['media_type'] == 'show' or metadata['media_type'] == 'artist': if metadata['media_type'] == 'show' or metadata['media_type'] == 'artist':
# check grandparent_rating_key (2 tables) # check grandparent_rating_key (2 tables)
monitor_db.action('UPDATE session_history SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', query = (
[new_key, old_key]) 'SELECT id FROM session_history '
monitor_db.action('UPDATE session_history_metadata SET grandparent_rating_key = ? WHERE grandparent_rating_key = ?', 'WHERE grandparent_rating_key = ? '
[new_key, old_key]) )
args = [old_key]
if _UPDATE_METADATA_IDS['grandparent_rating_key_ids']:
query += (
'AND id NOT IN (%s)' % ','.join(_UPDATE_METADATA_IDS['grandparent_rating_key_ids'])
)
ids = [str(row['id']) for row in monitor_db.select(query, args)]
if ids:
_UPDATE_METADATA_IDS['grandparent_rating_key_ids'].update(ids)
else:
continue
monitor_db.action(
'UPDATE session_history SET grandparent_rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
monitor_db.action(
'UPDATE session_history_metadata SET grandparent_rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
elif metadata['media_type'] == 'season' or metadata['media_type'] == 'album': elif metadata['media_type'] == 'season' or metadata['media_type'] == 'album':
# check parent_rating_key (2 tables) # check parent_rating_key (2 tables)
monitor_db.action('UPDATE session_history SET parent_rating_key = ? WHERE parent_rating_key = ?', query = (
[new_key, old_key]) 'SELECT id FROM session_history '
monitor_db.action('UPDATE session_history_metadata SET parent_rating_key = ? WHERE parent_rating_key = ?', 'WHERE parent_rating_key = ? '
[new_key, old_key]) )
args = [old_key]
if _UPDATE_METADATA_IDS['parent_rating_key_ids']:
query += (
'AND id NOT IN (%s)' % ','.join(_UPDATE_METADATA_IDS['parent_rating_key_ids'])
)
ids = [str(row['id']) for row in monitor_db.select(query, args)]
if ids:
_UPDATE_METADATA_IDS['parent_rating_key_ids'].update(ids)
else:
continue
monitor_db.action(
'UPDATE session_history SET parent_rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
monitor_db.action(
'UPDATE session_history_metadata SET parent_rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
else: else:
# check rating_key (2 tables) # check rating_key (2 tables)
monitor_db.action('UPDATE session_history SET rating_key = ? WHERE rating_key = ?', query = (
[new_key, old_key]) 'SELECT id FROM session_history '
monitor_db.action('UPDATE session_history_media_info SET rating_key = ? WHERE rating_key = ?', 'WHERE rating_key = ? '
[new_key, old_key]) )
args = [old_key]
if _UPDATE_METADATA_IDS['rating_key_ids']:
query += (
'AND id NOT IN (%s)' % ','.join(_UPDATE_METADATA_IDS['rating_key_ids'])
)
ids = [str(row['id']) for row in monitor_db.select(query, args)]
if ids:
_UPDATE_METADATA_IDS['rating_key_ids'].update(ids)
else:
continue
monitor_db.action(
'UPDATE session_history SET rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
monitor_db.action(
'UPDATE session_history_media_info SET rating_key = ? '
'WHERE id IN (%s)' % ','.join(ids),
[new_key]
)
monitor_db.action(
'INSERT INTO update_metadata (rating_key_id) '
'VALUES %s' % ','.join(['(?)'] * len(ids)),
ids
)
# update session_history_metadata table # update session_history_metadata table
self.update_metadata_details(old_key, new_key, metadata) self.update_metadata_details(old_key, new_key, metadata, ids)
return 'Updated metadata in database.' return 'Updated metadata in database.'
else: else:
return 'Unable to update metadata in database. No changes were made.' return 'Unable to update metadata in database. No changes were made.'
def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None): def update_metadata_details(self, old_rating_key='', new_rating_key='', metadata=None, ids=None):
if metadata: if metadata:
# Create full_title # Create full_title
@ -1909,8 +2001,9 @@ class DataFactory(object):
monitor_db = database.MonitorDatabase() monitor_db = database.MonitorDatabase()
query = 'UPDATE session_history SET section_id = ? WHERE rating_key = ?' query = 'UPDATE session_history SET section_id = ? ' \
args = [metadata['section_id'], new_rating_key] 'WHERE id IN (%s)' % ','.join(ids)
args = [metadata['section_id']]
monitor_db.action(query=query, args=args) monitor_db.action(query=query, args=args)
# Update the session_history_metadata table # Update the session_history_metadata table
@ -1922,7 +2015,7 @@ class DataFactory(object):
'added_at = ?, updated_at = ?, last_viewed_at = ?, content_rating = ?, summary = ?, ' \ 'added_at = ?, updated_at = ?, last_viewed_at = ?, content_rating = ?, summary = ?, ' \
'tagline = ?, rating = ?, duration = ?, guid = ?, directors = ?, writers = ?, actors = ?, ' \ 'tagline = ?, rating = ?, duration = ?, guid = ?, directors = ?, writers = ?, actors = ?, ' \
'genres = ?, studio = ?, labels = ? ' \ 'genres = ?, studio = ?, labels = ? ' \
'WHERE rating_key = ?' 'WHERE id IN (%s)' % ','.join(ids)
args = [metadata['rating_key'], metadata['parent_rating_key'], metadata['grandparent_rating_key'], args = [metadata['rating_key'], metadata['parent_rating_key'], metadata['grandparent_rating_key'],
metadata['title'], metadata['parent_title'], metadata['grandparent_title'], metadata['title'], metadata['parent_title'], metadata['grandparent_title'],
@ -1932,8 +2025,7 @@ class DataFactory(object):
metadata['year'], metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'], metadata['year'], metadata['originally_available_at'], metadata['added_at'], metadata['updated_at'],
metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['tagline'], metadata['last_viewed_at'], metadata['content_rating'], metadata['summary'], metadata['tagline'],
metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres, metadata['rating'], metadata['duration'], metadata['guid'], directors, writers, actors, genres,
metadata['studio'], labels, metadata['studio'], labels]
old_rating_key]
monitor_db.action(query=query, args=args) monitor_db.action(query=query, args=args)

View file

@ -5145,7 +5145,7 @@ class WebInterface(object):
@cherrypy.tools.json_out() @cherrypy.tools.json_out()
@requireAuth(member_of("admin")) @requireAuth(member_of("admin"))
@addtoapi() @addtoapi()
def update_metadata_details(self, old_rating_key, new_rating_key, media_type, **kwargs): def update_metadata_details(self, old_rating_key, new_rating_key, media_type, single_update=False, **kwargs):
""" Update the metadata in the Tautulli database by matching rating keys. """ Update the metadata in the Tautulli database by matching rating keys.
Also updates all parents or children of the media item if it is a show/season/episode Also updates all parents or children of the media item if it is a show/season/episode
or artist/album/track. or artist/album/track.
@ -5163,6 +5163,8 @@ class WebInterface(object):
None None
``` ```
""" """
single_update = helpers.bool_true(single_update)
if new_rating_key: if new_rating_key:
data_factory = datafactory.DataFactory() data_factory = datafactory.DataFactory()
pms_connect = pmsconnect.PmsConnect() pms_connect = pmsconnect.PmsConnect()
@ -5172,7 +5174,8 @@ class WebInterface(object):
result = data_factory.update_metadata(old_key_list=old_key_list, result = data_factory.update_metadata(old_key_list=old_key_list,
new_key_list=new_key_list, new_key_list=new_key_list,
media_type=media_type) media_type=media_type,
single_update=single_update)
if result: if result:
return {'message': result} return {'message': result}