Added non-persistent functinality to the TickerHandler, for specific use with OOB.

This commit is contained in:
Griatch 2016-03-24 19:44:18 +01:00
parent e09a172854
commit bece57f067
4 changed files with 36 additions and 20 deletions

View file

@ -777,12 +777,13 @@ class CmdTickers(MuxCommand):
if not all_subs: if not all_subs:
self.caller.msg("No tickers are currently active.") self.caller.msg("No tickers are currently active.")
return return
table = EvTable("tick(s)", "object", "path/methodname", "idstring") table = EvTable("tick(s)", "object", "path/methodname", "idstring", "db")
for sub in all_subs: for sub in all_subs:
table.add_row(sub[3], table.add_row(sub[3],
sub[1] or "[None]", sub[1] or "[None]",
sub[1] if sub[1] else sub[2], sub[1] if sub[1] else sub[2],
sub[4] or "[Unset]") sub[4] or "[Unset]",
"*" if sub[5] else "-")
self.caller.msg("|wActive tickers|n:\n" + unicode(table)) self.caller.msg("|wActive tickers|n:\n" + unicode(table))

View file

@ -136,6 +136,7 @@ class ExtendedLoopingCall(LoopingCall):
return interval - (total_runtime % self.interval) return interval - (total_runtime % self.interval)
return None return None
class ScriptBase(with_metaclass(TypeclassBase, ScriptDB)): class ScriptBase(with_metaclass(TypeclassBase, ScriptDB)):
""" """
Base class for scripts. Don't inherit from this, inherit from the Base class for scripts. Don't inherit from this, inherit from the

View file

@ -110,7 +110,6 @@ class Ticker(object):
# try object method # try object method
if not obj or not obj.pk: if not obj or not obj.pk:
# object was deleted between calls # object was deleted between calls
log_err("Obj undefined. Removing ticker.")
to_remove.append(store_key) to_remove.append(store_key)
continue continue
else: else:
@ -219,7 +218,7 @@ class TickerPool(object):
args (any, optional): Arguments to send to the hook method. args (any, optional): Arguments to send to the hook method.
""" """
_, _, _, interval, _ = store_key _, _, _, interval, _, _ = store_key
if not interval: if not interval:
log_err(_ERROR_ADD_TICKER.format(store_key=store_key)) log_err(_ERROR_ADD_TICKER.format(store_key=store_key))
return return
@ -236,7 +235,7 @@ class TickerPool(object):
store_key (str): Unique storage hash to remove store_key (str): Unique storage hash to remove
""" """
_, _, _, interval, _ = store_key _, _, _, interval, _, _ = store_key
if interval in self.tickers: if interval in self.tickers:
self.tickers[interval].remove(store_key) self.tickers[interval].remove(store_key)
if not self.tickers[interval]: if not self.tickers[interval]:
@ -310,7 +309,7 @@ class TickerHandler(object):
raise TypeError("%s is not a callable function or method." % callback) raise TypeError("%s is not a callable function or method." % callback)
return outobj, outpath, outcallfunc return outobj, outpath, outcallfunc
def _store_key(self, obj, path, interval, callfunc, idstring=""): def _store_key(self, obj, path, interval, callfunc, idstring="", persistent=True):
""" """
Tries to create a store_key for the object. Returns a tuple Tries to create a store_key for the object. Returns a tuple
(isdb, store_key) where isdb is a boolean True if obj was a (isdb, store_key) where isdb is a boolean True if obj was a
@ -325,6 +324,8 @@ class TickerHandler(object):
stored in the key; that is uniquely identified with the python-path. stored in the key; that is uniquely identified with the python-path.
idstring (str, optional): Additional separator between idstring (str, optional): Additional separator between
different subscription types. different subscription types.
persistent (bool, optional): If this ticker should survive a system
shutdown or not.
Returns: Returns:
isdb_and_store_key (tuple): A tuple `(obj, path, interval, isdb_and_store_key (tuple): A tuple `(obj, path, interval,
@ -335,10 +336,12 @@ class TickerHandler(object):
`obj_or_path` is a python-path. `obj_or_path` is a python-path.
""" """
interval = int(interval)
persistent = bool(persistent)
outobj = obj if obj and hasattr(obj, "db_key") else None outobj = obj if obj and hasattr(obj, "db_key") else None
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) return (outobj, methodname, outpath, interval, idstring, persistent)
def save(self): def save(self):
""" """
@ -363,21 +366,31 @@ class TickerHandler(object):
# 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)
def restore(self): def restore(self, server_reload=True):
""" """
Restore ticker_storage from database and re-initialize the Restore ticker_storage from database and re-initialize the
handler from storage. This is triggered by the server at handler from storage. This is triggered by the server at
restart. restart.
Args:
server_reload (bool): If this is False, it means the server
went through a cold reboot and all
non-persistent tickers must be killed.
""" """
# load stored command instructions and use them to re-initialize handler # load stored command instructions and use them to re-initialize handler
ticker_storage = ServerConfig.objects.conf(key=self.save_name) restored_tickers = ServerConfig.objects.conf(key=self.save_name)
if ticker_storage: if restored_tickers:
# the dbunserialize will convert all serialized dbobjs to real objects # the dbunserialize will convert all serialized dbobjs to real objects
self.ticker_storage = dbunserialize(ticker_storage)
for store_key, (args, kwargs) in self.ticker_storage.iteritems(): restored_tickers = dbunserialize(restored_tickers)
ticker_storage = {}
for store_key, (args, kwargs) in restored_tickers.iteritems():
try: try:
obj, methodname, path, interval, idstring = store_key obj, methodname, path, interval, idstring, persistent = store_key
if not persistent and not server_reload:
# this ticker will not be restarted
continue
if obj and methodname: if obj and methodname:
kwargs["_callback"] = methodname kwargs["_callback"] = methodname
kwargs["_obj"] = obj kwargs["_obj"] = obj
@ -386,15 +399,17 @@ class TickerHandler(object):
callback = variable_from_module(modname, varname) callback = variable_from_module(modname, varname)
kwargs["_callback"] = callback kwargs["_callback"] = callback
kwargs["_obj"] = None kwargs["_obj"] = None
ticker_storage[store_key] = (args, kwargs)
except Exception as err: except Exception as err:
# this suggests a malformed save or missing objects # this suggests a malformed save or missing objects
log_err("%s\nTickerhandler: Removing malformed ticker: %s" % (err, str(store_key))) log_err("%s\nTickerhandler: Removing malformed ticker: %s" % (err, str(store_key)))
continue continue
self.ticker_storage = ticker_storage
self.ticker_pool.add(store_key, *args, **kwargs) self.ticker_pool.add(store_key, *args, **kwargs)
def add(self, interval=60, callback=None, idstring="", *args, **kwargs): def add(self, interval=60, callback=None, idstring="", persistent=True, *args, **kwargs):
""" """
Add object to tickerhandler Add subscription to tickerhandler
Args: Args:
interval (int, optional): Interval in seconds between calling interval (int, optional): Interval in seconds between calling
@ -407,6 +422,9 @@ class TickerHandler(object):
this ticker-subscription from others with the same this ticker-subscription from others with the same
interval. Allows for managing multiple calls with interval. Allows for managing multiple calls with
the same time interval and callback. the same time interval and callback.
persistent (bool, optional): A ticker will always survive
a server reload. If this is unset, the ticker will be
deleted by a server shutdown.
args, kwargs (optional): These will be passed into the args, kwargs (optional): These will be passed into the
callback every time it is called. callback every time it is called.
@ -419,9 +437,8 @@ class TickerHandler(object):
when wanting to modify/remove the ticker later. when wanting to modify/remove the ticker later.
""" """
interval = int(interval)
obj, path, callfunc = self._get_callback(callback) obj, path, callfunc = self._get_callback(callback)
store_key = self._store_key(obj, path, interval, callfunc, idstring) store_key = self._store_key(obj, path, interval, callfunc, idstring, persistent)
self.ticker_storage[store_key] = (args, kwargs) self.ticker_storage[store_key] = (args, kwargs)
self.save() self.save()
kwargs["_obj"] = obj kwargs["_obj"] = obj

View file

@ -549,9 +549,6 @@ class TypedObject(SharedMemoryModel):
""" """
global TICKER_HANDLER global TICKER_HANDLER
if not TICKER_HANDLER:
from evennia.scripts.tickerhandler import TICKER_HANDLER
TICKER_HANDLER.remove(self) # removes objects' all ticker subscriptions
self.permissions.clear() self.permissions.clear()
self.attributes.clear() self.attributes.clear()
self.aliases.clear() self.aliases.clear()