Workaround addon service not starting prior to plugin invocation #1298

This commit is contained in:
MoojMidge 2025-10-11 13:26:17 +11:00
parent fe2b0b8d74
commit 3b4b7a4ea0
6 changed files with 52 additions and 9 deletions

View file

@ -56,6 +56,7 @@ VALUE_TO_STR = {
# Flags
ABORT_FLAG = 'abort_requested'
BUSY_FLAG = 'busy'
SERVICE_RUNNING_FLAG = 'service_monitor_running'
WAIT_END_FLAG = 'builtin_completed'
TRAKT_PAUSE_FLAG = 'script.trakt.paused'
@ -220,6 +221,7 @@ __all__ = (
# Flags
'ABORT_FLAG',
'BUSY_FLAG',
'SERVICE_RUNNING_FLAG',
'TRAKT_PAUSE_FLAG',
'WAIT_END_FLAG',

View file

@ -684,7 +684,7 @@ class AbstractContext(object):
def tear_down(self):
pass
def ipc_exec(self, target, timeout=None, payload=None):
def ipc_exec(self, target, timeout=None, payload=None, raise_exc=False):
raise NotImplementedError()
@staticmethod

View file

@ -28,12 +28,14 @@ from ...compatibility import (
from ...constants import (
ABORT_FLAG,
ADDON_ID,
BUSY_FLAG,
CHANNEL_ID,
CONTENT,
FOLDER_NAME,
PLAYLIST_ID,
PLAY_FORCE_AUDIO,
SERVICE_IPC,
SERVICE_RUNNING_FLAG,
SORT,
URI,
VIDEO_ID,
@ -972,7 +974,15 @@ class XbmcContext(AbstractContext):
except AttributeError:
pass
def ipc_exec(self, target, timeout=None, payload=None):
def ipc_exec(self, target, timeout=None, payload=None, raise_exc=False):
if not XbmcContextUI.get_property(SERVICE_RUNNING_FLAG, as_bool=True):
msg = 'Service IPC - Monitor has not started'
XbmcContextUI.set_property(SERVICE_RUNNING_FLAG, BUSY_FLAG)
if raise_exc:
raise RuntimeError(msg)
self.log.warning_trace(msg)
return None
data = {'target': target, 'response_required': bool(timeout)}
if payload:
data.update(payload)

View file

@ -36,7 +36,12 @@ class AccessManager(JSONStore):
}
def __init__(self, context):
self._user = None
self._last_origin = None
super(AccessManager, self).__init__('access_manager.json', context)
def init(self):
super(AccessManager, self).init()
access_manager_data = self._data['access_manager']
self._user = access_manager_data.get('current_user', 0)
self._last_origin = access_manager_data.get('last_origin', ADDON_ID)
@ -204,7 +209,8 @@ class AccessManager(JSONStore):
Returns users
:return: users
"""
return self._data['access_manager'].get('users', {})
data = self._data if self._loaded else self.get_data()
return data['access_manager'].get('users', {})
def add_user(self, username='', user=None):
"""
@ -546,7 +552,8 @@ class AccessManager(JSONStore):
Returns developers
:return: dict, developers
"""
return self._data['access_manager'].get('developers', {})
data = self._data if self._loaded else self.get_data()
return data['access_manager'].get('developers', {})
def add_new_developer(self, addon_id):
"""

View file

@ -38,9 +38,17 @@ class JSONStore(object):
self.filepath = None
self._context = context
self._loaded = False
self._data = {}
self.load(stacklevel=3)
self.set_defaults()
self.init()
def init(self):
if self.load(stacklevel=4):
self._loaded = True
self.set_defaults()
else:
self.set_defaults(reset=True)
return self._loaded
def set_defaults(self, reset=False):
raise NotImplementedError
@ -81,6 +89,7 @@ class JSONStore(object):
FILE_WRITE,
timeout=5,
payload={'filepath': filepath},
raise_exc=True,
)
if response is False:
raise IOError
@ -92,7 +101,7 @@ class JSONStore(object):
else:
with open(filepath, mode='w', encoding='utf-8') as file:
file.write(to_unicode(_data))
except (IOError, OSError):
except (RuntimeError, IOError, OSError):
self.log.exception(('Access error', 'File: %s'),
filepath,
stacklevel=stacklevel)
@ -119,6 +128,7 @@ class JSONStore(object):
FILE_READ,
timeout=5,
payload={'filepath': filepath},
raise_exc=True,
) is not False:
data = self._context.get_ui().get_property(
'-'.join((FILE_READ, filepath)),
@ -135,17 +145,23 @@ class JSONStore(object):
data,
object_pairs_hook=(self._process_data if process else None),
)
except (IOError, OSError):
except (RuntimeError, IOError, OSError):
self.log.exception(('Access error', 'File: %s'),
filepath,
stacklevel=stacklevel)
return False
except (TypeError, ValueError):
self.log.exception(('Invalid data', 'Data: {data!r}'),
data=data,
stacklevel=stacklevel)
return False
return True
def get_data(self, process=True, fallback=True, stacklevel=2):
if not self._loaded:
self.init()
data = self._data
try:
if not data:
raise ValueError
@ -160,7 +176,9 @@ class JSONStore(object):
if fallback:
self.set_defaults(reset=True)
return self.get_data(process=process, fallback=False)
raise exc
if self._loaded:
raise exc
return data
def load_data(self, data, process=True, stacklevel=2):
try:

View file

@ -15,6 +15,7 @@ from .constants import (
ABORT_FLAG,
ARTIST,
BOOKMARK_ID,
BUSY_FLAG,
CHANNEL_ID,
CONTAINER_ID,
CONTAINER_POSITION,
@ -24,6 +25,7 @@ from .constants import (
PLAYLIST_ITEM_ID,
PLAY_COUNT,
PLUGIN_SLEEPING,
SERVICE_RUNNING_FLAG,
SUBSCRIPTION_ID,
TEMP_PATH,
TITLE,
@ -67,6 +69,9 @@ def run():
localize = context.localize
clear_property(ABORT_FLAG)
if ui.get_property(SERVICE_RUNNING_FLAG) == BUSY_FLAG:
monitor.refresh_container()
set_property(SERVICE_RUNNING_FLAG)
# wipe add-on temp folder on updates/restarts (subtitles, and mpd files)
rm_dir(TEMP_PATH)
@ -240,6 +245,7 @@ def run():
break
set_property(ABORT_FLAG)
clear_property(SERVICE_RUNNING_FLAG)
# clean up any/all playback monitoring threads
player.cleanup_threads(only_ended=False)