Make tickerhandler correctly clean subs to deleted objs.
Also makes the dbunserialize mechanism a little more robust, making it return None instead of crashing when unpacking an invalid packed-tuple.
This commit is contained in:
parent
25e1126809
commit
bdcc093c23
2 changed files with 37 additions and 17 deletions
|
|
@ -66,7 +66,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||||
from evennia.scripts.scripts import ExtendedLoopingCall
|
from evennia.scripts.scripts import ExtendedLoopingCall
|
||||||
from evennia.server.models import ServerConfig
|
from evennia.server.models import ServerConfig
|
||||||
from evennia.utils.logger import log_trace, log_err
|
from evennia.utils.logger import log_trace, log_err
|
||||||
from evennia.utils.dbserialize import dbserialize, dbunserialize
|
from evennia.utils.dbserialize import dbserialize, dbunserialize, pack_dbobj, unpack_dbobj
|
||||||
from evennia.utils import variable_from_module
|
from evennia.utils import variable_from_module
|
||||||
|
|
||||||
_GA = object.__getattribute__
|
_GA = object.__getattribute__
|
||||||
|
|
@ -339,7 +339,8 @@ class TickerHandler(object):
|
||||||
Tries to create a store_key for the object.
|
Tries to create a store_key for the object.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
obj (Object or None): Subscribing object if any.
|
obj (Object, tuple or None): Subscribing object if any. If a tuple, this is
|
||||||
|
a packed_obj tuple from dbserialize.
|
||||||
path (str or None): Python-path to callable, if any.
|
path (str or None): Python-path to callable, if any.
|
||||||
interval (int): Ticker interval.
|
interval (int): Ticker interval.
|
||||||
callfunc (callable or str): This is either the callable function or
|
callfunc (callable or str): This is either the callable function or
|
||||||
|
|
@ -361,7 +362,7 @@ class TickerHandler(object):
|
||||||
"""
|
"""
|
||||||
interval = int(interval)
|
interval = int(interval)
|
||||||
persistent = bool(persistent)
|
persistent = bool(persistent)
|
||||||
outobj = obj if obj and hasattr(obj, "db_key") else None
|
outobj = pack_dbobj(obj)
|
||||||
outpath = path if path and isinstance(path, basestring) else None
|
outpath = path if path and isinstance(path, basestring) else None
|
||||||
methodname = callfunc if callfunc and isinstance(callfunc, basestring) else None
|
methodname = callfunc if callfunc and isinstance(callfunc, basestring) else None
|
||||||
return (outobj, methodname, outpath, interval, idstring, persistent)
|
return (outobj, methodname, outpath, interval, idstring, persistent)
|
||||||
|
|
@ -375,16 +376,21 @@ class TickerHandler(object):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if self.ticker_storage:
|
if self.ticker_storage:
|
||||||
|
# get the current times so the tickers can be restarted with a delay later
|
||||||
start_delays = dict((interval, ticker.task.next_call_time())
|
start_delays = dict((interval, ticker.task.next_call_time())
|
||||||
for interval, ticker in self.ticker_pool.tickers.items())
|
for interval, ticker in self.ticker_pool.tickers.items())
|
||||||
|
|
||||||
|
# remove any subscriptions that lost its object in the interim
|
||||||
|
to_save = {store_key: (args, kwargs) for store_key, (args, kwargs) in self.ticker_storage.items()
|
||||||
|
if inspect.ismethod(store_key[1]) and (not "_obj" in kwargs or kwargs["_obj"].pk)}
|
||||||
|
|
||||||
# update the timers for the tickers
|
# update the timers for the tickers
|
||||||
#for (obj, interval, idstring), (args, kwargs) in self.ticker_storage.items():
|
for store_key, (args, kwargs) in to_save.items():
|
||||||
for store_key, (args, kwargs) in self.ticker_storage.items():
|
|
||||||
interval = store_key[1]
|
interval = store_key[1]
|
||||||
# this is a mutable, so it's updated in-place in ticker_storage
|
# this is a mutable, so it's updated in-place in ticker_storage
|
||||||
kwargs["_start_delay"] = start_delays.get(interval, None)
|
kwargs["_start_delay"] = start_delays.get(interval, None)
|
||||||
ServerConfig.objects.conf(key=self.save_name,
|
kwargs.pop("_obj", None)
|
||||||
value=dbserialize(self.ticker_storage))
|
ServerConfig.objects.conf(key=self.save_name, value=dbserialize(to_save))
|
||||||
else:
|
else:
|
||||||
# make sure we have nothing lingering in the database
|
# make sure we have nothing lingering in the database
|
||||||
ServerConfig.objects.conf(key=self.save_name, delete=True)
|
ServerConfig.objects.conf(key=self.save_name, delete=True)
|
||||||
|
|
@ -410,12 +416,21 @@ class TickerHandler(object):
|
||||||
ticker_storage = {}
|
ticker_storage = {}
|
||||||
for store_key, (args, kwargs) in restored_tickers.iteritems():
|
for store_key, (args, kwargs) in restored_tickers.iteritems():
|
||||||
try:
|
try:
|
||||||
obj, methodname, path, interval, idstring, persistent = store_key
|
obj, callfunc, path, interval, idstring, persistent = store_key
|
||||||
if not persistent and not server_reload:
|
if not persistent and not server_reload:
|
||||||
# this ticker will not be restarted
|
# this ticker will not be restarted
|
||||||
continue
|
continue
|
||||||
if obj and methodname:
|
if inspect.ismethod(callfunc) and not obj:
|
||||||
kwargs["_callback"] = methodname
|
continue
|
||||||
|
if obj:
|
||||||
|
try:
|
||||||
|
obj = unpack_dbobj(obj)
|
||||||
|
except IndexError:
|
||||||
|
# this happens with an old save, where obj was
|
||||||
|
# saved as itself; we must re-do the store_key.
|
||||||
|
store_key = self._store_key(obj, path, interval, callfunc, idstring, persistent)
|
||||||
|
if obj and callfunc:
|
||||||
|
kwargs["_callback"] = callfunc
|
||||||
kwargs["_obj"] = obj
|
kwargs["_obj"] = obj
|
||||||
elif path:
|
elif path:
|
||||||
modname, varname = path.rsplit(".", 1)
|
modname, varname = path.rsplit(".", 1)
|
||||||
|
|
@ -550,7 +565,8 @@ class TickerHandler(object):
|
||||||
"""
|
"""
|
||||||
store_keys = []
|
store_keys = []
|
||||||
for ticker in self.ticker_pool.tickers.itervalues():
|
for ticker in self.ticker_pool.tickers.itervalues():
|
||||||
store_keys.extend([store_key for store_key in ticker.subscriptions])
|
for (objtup, callfunc, path, interval, idstring, persistent), (args, kwargs) in ticker.subscriptions.iteritems():
|
||||||
|
store_keys.append((kwargs.get("_obj", None), callfunc, path, interval, idstring, persistent))
|
||||||
return store_keys
|
return store_keys
|
||||||
|
|
||||||
# main tickerhandler
|
# main tickerhandler
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,11 @@ def _TO_DATESTRING(obj):
|
||||||
return _GA(obj, "db_date_created").strftime(_DATESTRING)
|
return _GA(obj, "db_date_created").strftime(_DATESTRING)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# this can happen if object is not yet saved - no datestring is then set
|
# this can happen if object is not yet saved - no datestring is then set
|
||||||
obj.save()
|
try:
|
||||||
|
obj.save()
|
||||||
|
except AttributeError:
|
||||||
|
# we have received a None object, for example due to an erroneous save.
|
||||||
|
return None
|
||||||
return _GA(obj, "db_date_created").strftime(_DATESTRING)
|
return _GA(obj, "db_date_created").strftime(_DATESTRING)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue