make intents thread safe by using DictProxy
This commit is contained in:
@@ -25,7 +25,6 @@ import interface
|
||||
sys.modules["interface"] = interface
|
||||
|
||||
from subzero.constants import OS_PLEX_USERAGENT, PERSONAL_MEDIA_IDENTIFIER
|
||||
from subzero import intent
|
||||
from interface.menu import *
|
||||
from support.plex_media import media_to_videos, get_media_item_ids, scan_videos
|
||||
from support.subtitlehelpers import get_subtitles_from_metadata, force_utf8
|
||||
@@ -33,6 +32,7 @@ from support.helpers import notify_executable
|
||||
from support.storage import store_subtitle_info, whack_missing_parts
|
||||
from support.items import is_ignored
|
||||
from support.config import config
|
||||
from support.lib import get_intent
|
||||
|
||||
|
||||
def Start():
|
||||
@@ -42,6 +42,10 @@ def Start():
|
||||
# configured cache to be in memory as per https://github.com/Diaoul/subliminal/issues/303
|
||||
subliminal.region.configure('dogpile.cache.memory')
|
||||
|
||||
# clear expired intents
|
||||
intent = get_intent()
|
||||
intent.cleanup()
|
||||
|
||||
# init defaults; perhaps not the best idea to use ValidatePrefs here, but we'll see
|
||||
ValidatePrefs()
|
||||
Log.Debug(config.full_version)
|
||||
@@ -207,6 +211,7 @@ class SubZeroAgent(object):
|
||||
|
||||
def update(self, metadata, media, lang):
|
||||
Log.Debug("Sub-Zero %s, %s update called" % (config.version, self.agent_type))
|
||||
intent = get_intent()
|
||||
|
||||
if not media:
|
||||
Log.Error("Called with empty media, something is really wrong with your setup!")
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import types
|
||||
|
||||
from support.items import get_kind, get_item_thumb
|
||||
from subzero import intent
|
||||
from support.helpers import get_video_display_title
|
||||
from support.ignore import ignore_list
|
||||
from support.lib import get_intent
|
||||
from subzero.constants import ICON
|
||||
from subzero.func import debouncer
|
||||
|
||||
@@ -93,6 +93,8 @@ def set_refresh_menu_state(state_or_media, media_type="movies"):
|
||||
title = get_video_display_title("show", ep.title, parent_title=media.title, season=int(season), episode=int(episode))
|
||||
else:
|
||||
title = get_video_display_title("movie", media.title)
|
||||
|
||||
intent = get_intent()
|
||||
force_refresh = intent.get("force", media_id)
|
||||
|
||||
Dict["current_refresh_state"] = u"%sRefreshing %s" % ("Force-" if force_refresh else "", unicode(title))
|
||||
|
||||
@@ -6,8 +6,7 @@ import types
|
||||
import os
|
||||
from ignore import ignore_list
|
||||
from helpers import is_recent, get_plex_item_display_title, query_plex
|
||||
from subzero import intent
|
||||
from lib import Plex
|
||||
from lib import Plex, get_intent
|
||||
from config import config, IGNORE_FN
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -260,11 +259,16 @@ def is_ignored(rating_key, item=None):
|
||||
|
||||
|
||||
def refresh_item(rating_key, force=False, timeout=8000, refresh_kind=None, parent_rating_key=None):
|
||||
intent = get_intent()
|
||||
|
||||
# timeout actually is the time for which the intent will be valid
|
||||
if force:
|
||||
Log.Debug("Setting intent for force-refresh of %s to timeout: %s", rating_key, timeout)
|
||||
intent.set("force", rating_key, timeout=timeout)
|
||||
|
||||
# force Dict.Save()
|
||||
intent.store.save()
|
||||
|
||||
refresh = [rating_key]
|
||||
|
||||
if refresh_kind == "season":
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# coding=utf-8
|
||||
|
||||
import plex
|
||||
from subzero.intent import TempIntent
|
||||
from subzero.lib.dict import DictProxy
|
||||
from subzero.lib.httpfake import PlexPyNativeResponseProxy
|
||||
|
||||
|
||||
@@ -35,3 +37,18 @@ class PlexPyNativeRequestProxy(object):
|
||||
plex.request.Request = PlexPyNativeRequestProxy
|
||||
|
||||
Plex = plex.Plex
|
||||
|
||||
|
||||
class IntentDictStorage(DictProxy):
|
||||
store = "intent"
|
||||
|
||||
def setup_defaults(self):
|
||||
return {"force": {}}
|
||||
|
||||
|
||||
def get_intent():
|
||||
"""
|
||||
use this to get an intent from inside a separate thread
|
||||
:return:
|
||||
"""
|
||||
return TempIntent(store=IntentDictStorage(Dict))
|
||||
|
||||
@@ -5,7 +5,7 @@ import subliminal
|
||||
import helpers
|
||||
|
||||
from items import get_item
|
||||
from subzero import intent
|
||||
from lib import get_intent
|
||||
|
||||
|
||||
def get_metadata_dict(item, part, add):
|
||||
@@ -113,8 +113,10 @@ def scan_videos(videos, kind="series"):
|
||||
"""
|
||||
ret = {}
|
||||
for video in videos:
|
||||
intent = get_intent()
|
||||
force_refresh = intent.get("force", video["id"], video["series_id"], video["season_id"])
|
||||
Log.Debug("Determining force-refresh, result: %s" % force_refresh)
|
||||
Log.Debug("Determining force-refresh (video: %s, series: %s, season: %s), result: %s"
|
||||
% (video["id"], video["series_id"], video["season_id"], force_refresh))
|
||||
|
||||
hints = helpers.get_item_hints(video["title"], kind, series=video["series"] if kind == "series" else None)
|
||||
video["plex_part"].fps = get_stream_fps(video["plex_part"].streams)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# coding=utf-8
|
||||
|
||||
from intent import intent
|
||||
|
||||
OS_PLEX_USERAGENT = 'plexapp.com v9.0'
|
||||
|
||||
DEPENDENCY_MODULE_NAMES = ['subliminal', 'subliminal_patch', 'enzyme', 'guessit', 'requests']
|
||||
|
||||
@@ -6,25 +6,16 @@ import threading
|
||||
lock = threading.Lock()
|
||||
|
||||
|
||||
class TempIntent(dict):
|
||||
class TempIntent(object):
|
||||
timeout = 1000 # milliseconds
|
||||
store = None
|
||||
|
||||
def __init__(self, timeout=1000):
|
||||
def __init__(self, timeout=1000, store=None):
|
||||
self.timeout = timeout
|
||||
with lock:
|
||||
self.store = {}
|
||||
if store is None:
|
||||
raise NotImplementedError
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self:
|
||||
return self[name]
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
self[name] = value
|
||||
|
||||
def __delattr__(self, name):
|
||||
if name in self:
|
||||
del self[name]
|
||||
self.store = store
|
||||
|
||||
def get(self, kind, *keys):
|
||||
with lock:
|
||||
@@ -37,13 +28,13 @@ class TempIntent(dict):
|
||||
continue
|
||||
|
||||
# valid kind?
|
||||
if kind in self["store"]:
|
||||
if kind in self.store:
|
||||
now = datetime.datetime.now()
|
||||
|
||||
# iter all known kinds (previously created)
|
||||
for known_key in self["store"][kind].keys():
|
||||
for known_key in self.store[kind].keys():
|
||||
# may need locking, for now just play it safe
|
||||
ends = self["store"][kind].get(known_key, None)
|
||||
ends = self.store[kind].get(known_key, None)
|
||||
if not ends:
|
||||
continue
|
||||
|
||||
@@ -57,7 +48,7 @@ class TempIntent(dict):
|
||||
|
||||
if timed_out:
|
||||
try:
|
||||
del self["store"][kind][key]
|
||||
del self.store[kind][key]
|
||||
except:
|
||||
continue
|
||||
|
||||
@@ -67,22 +58,28 @@ class TempIntent(dict):
|
||||
|
||||
def resolve(self, kind, key):
|
||||
with lock:
|
||||
if kind in self["store"] and key in self["store"][kind]:
|
||||
del self["store"][kind][key]
|
||||
if kind in self.store and key in self.store[kind]:
|
||||
del self.store[kind][key]
|
||||
return True
|
||||
return False
|
||||
|
||||
def set(self, kind, key, timeout=None):
|
||||
with lock:
|
||||
if kind not in self["store"]:
|
||||
self["store"][kind] = {}
|
||||
self["store"][kind][key] = datetime.datetime.now() + datetime.timedelta(milliseconds=timeout or self.timeout)
|
||||
if kind not in self.store:
|
||||
self.store[kind] = {}
|
||||
self.store[kind][key] = datetime.datetime.now() + datetime.timedelta(milliseconds=timeout or self.timeout)
|
||||
|
||||
def has(self, kind, key):
|
||||
with lock:
|
||||
if kind not in self["store"]:
|
||||
if kind not in self.store:
|
||||
return False
|
||||
return key in self["store"][kind]
|
||||
return key in self.store[kind]
|
||||
|
||||
def cleanup(self):
|
||||
now = datetime.datetime.now()
|
||||
for kind, data in self.store.items():
|
||||
for key, timeout in data.iteritems():
|
||||
if now > timeout:
|
||||
del self.store[kind][key]
|
||||
self.store.save()
|
||||
|
||||
intent = TempIntent()
|
||||
|
||||
@@ -10,6 +10,7 @@ class DictProxy(object):
|
||||
|
||||
if self.store not in self.Dict or not self.Dict[self.store]:
|
||||
self.Dict[self.store] = self.setup_defaults()
|
||||
self.save()
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name in self.Dict[self.store]:
|
||||
@@ -45,6 +46,9 @@ class DictProxy(object):
|
||||
def __delitem__(self, key):
|
||||
del self.Dict[self.store][key]
|
||||
|
||||
def save(self):
|
||||
self.Dict.Save()
|
||||
|
||||
def clear(self):
|
||||
del self.Dict[self.store]
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user