From 7670aa7a14e9d90647c758b7280588cf27b85d7b Mon Sep 17 00:00:00 2001 From: croneter Date: Sun, 25 Nov 2018 17:21:32 +0100 Subject: [PATCH] Fix OperationalError: Database is locked when video was deleted --- resources/lib/library_sync/full_sync.py | 14 +- .../lib/library_sync/process_metadata.py | 125 ++++++++++-------- 2 files changed, 74 insertions(+), 65 deletions(-) diff --git a/resources/lib/library_sync/full_sync.py b/resources/lib/library_sync/full_sync.py index 25aacdac..4d8a4400 100644 --- a/resources/lib/library_sync/full_sync.py +++ b/resources/lib/library_sync/full_sync.py @@ -4,7 +4,8 @@ from __future__ import absolute_import, division, unicode_literals from logging import getLogger from .get_metadata import GetMetadataTask, reset_collections -from .process_metadata import InitNewSection, UpdateLastSync, ProcessMetadata +from .process_metadata import InitNewSection, UpdateLastSync, ProcessMetadata, \ + DeleteItem from . import common, sections from .. import utils, timing, backgroundthread, variables as v, app from .. import plex_functions as PF, itemtypes @@ -64,12 +65,11 @@ class FullSync(common.libsync_mixin): Removes all the items that have NOT been updated (last_sync timestamp is different) """ - with self.context(self.current_sync) as c: - for plex_id in self.plexdb.plex_id_by_last_sync(self.plex_type, - self.current_sync): - if self.isCanceled(): - return - c.remove(plex_id, plex_type=self.plex_type) + for plex_id in self.plexdb.plex_id_by_last_sync(self.plex_type, + self.current_sync): + if self.isCanceled(): + return + self.queue.put(DeleteItem(plex_id)) @utils.log_time def process_playstate(self, iterator): diff --git a/resources/lib/library_sync/process_metadata.py b/resources/lib/library_sync/process_metadata.py index 03d4d6be..5fb2ca96 100644 --- a/resources/lib/library_sync/process_metadata.py +++ b/resources/lib/library_sync/process_metadata.py @@ -34,6 +34,11 @@ class UpdateLastSync(object): self.plex_id = plex_id +class DeleteItem(object): + def __init__(self, plex_id): + self.plex_id = plex_id + + class ProcessMetadata(backgroundthread.KillableThread, common.libsync_mixin): """ Not yet implemented for more than 1 thread - if ever. Only to be called by @@ -71,66 +76,14 @@ class ProcessMetadata(backgroundthread.KillableThread, common.libsync_mixin): % (self.current, self.total, self.title)) def run(self): - """ - Do the work - """ LOG.debug('Processing thread started') + if self.show_dialog: + self.dialog = xbmcgui.DialogProgressBG() + self.dialog.create(utils.lang(39714)) try: - if self.show_dialog: - self.dialog = xbmcgui.DialogProgressBG() - self.dialog.create(utils.lang(39714)) - # Init with the very first library section. This will block! - section = self.queue.get() - self.queue.task_done() - if section is None: - return - while not self.isCanceled(): - if section is None: - break - LOG.debug('Start processing section %s (%ss)', - section.name, section.plex_type) - self.current = 1 - self.processed = 0 - self.total = section.total - self.section_name = section.name - self.section_type_text = utils.lang( - v.TRANSLATION_FROM_PLEXTYPE[section.plex_type]) - profile = Profile() - profile.enable() - with section.context(self.last_sync) as context: - while not self.isCanceled(): - # grabs item from queue. This will block! - item = self.queue.get() - if isinstance(item, InitNewSection) or item is None: - section = item - self.queue.task_done() - break - elif isinstance(item, UpdateLastSync): - context.plexdb.update_last_sync(item.plex_id, - section.plex_type, - self.last_sync) - else: - try: - context.add_update(item['xml'][0], - section_name=section.name, - section_id=section.id, - children=item['children']) - except: - utils.ERROR(notify=True, cancel_sync=True) - self.title = item['xml'][0].get('title') - self.processed += 1 - self.update_progressbar() - self.current += 1 - if self.processed == 500: - self.processed = 0 - context.commit() - self.queue.task_done() - profile.disable() - string_io = StringIO() - stats = Stats(profile, stream=string_io).sort_stats('cumulative') - stats.print_stats() - LOG.info('cProfile result: ') - LOG.info(string_io.getvalue()) + self._run() + except: + utils.ERROR(notify=True, cancel_sync=True) finally: if self.dialog: self.dialog.close() @@ -139,3 +92,59 @@ class ProcessMetadata(backgroundthread.KillableThread, common.libsync_mixin): self.queue.get() self.queue.task_done() LOG.debug('Processing thread terminated') + + def _run(self): + """ + Do the work + """ + # Init with the very first library section. This will block! + section = self.queue.get() + self.queue.task_done() + if section is None: + return + while not self.isCanceled(): + if section is None: + break + LOG.debug('Start processing section %s (%ss)', + section.name, section.plex_type) + self.current = 1 + self.processed = 0 + self.total = section.total + self.section_name = section.name + self.section_type_text = utils.lang( + v.TRANSLATION_FROM_PLEXTYPE[section.plex_type]) + profile = Profile() + profile.enable() + with section.context(self.last_sync) as context: + while not self.isCanceled(): + # grabs item from queue. This will block! + item = self.queue.get() + if isinstance(item, dict): + context.add_update(item['xml'][0], + section_name=section.name, + section_id=section.id, + children=item['children']) + self.title = item['xml'][0].get('title') + self.processed += 1 + elif isinstance(item, UpdateLastSync): + context.plexdb.update_last_sync(item.plex_id, + section.plex_type, + self.last_sync) + elif isinstance(item, InitNewSection) or item is None: + section = item + self.queue.task_done() + break + else: + context.remove(item.plex_id, plex_type=section.plex_type) + self.update_progressbar() + self.current += 1 + if self.processed == 500: + self.processed = 0 + context.commit() + self.queue.task_done() + profile.disable() + string_io = StringIO() + stats = Stats(profile, stream=string_io).sort_stats('cumulative') + stats.print_stats() + LOG.info('cProfile result: ') + LOG.info(string_io.getvalue())