Created the ExtendedLoopingCall class for making resheduling of scripts a little more robust

This commit is contained in:
Griatch 2014-02-13 13:25:46 +01:00
parent d159f6731d
commit 6e4591d633

View file

@ -6,7 +6,7 @@ It also defines a few common scripts.
""" """
from time import time from time import time
from twisted.internet.defer import maybeDeferred from twisted.internet.defer import maybeDeferred, Deferred
from twisted.internet.task import LoopingCall from twisted.internet.task import LoopingCall
from django.conf import settings from django.conf import settings
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -23,6 +23,85 @@ _SESSIONS = None
_ATTRIBUTE_CACHE_MAXSIZE = settings.ATTRIBUTE_CACHE_MAXSIZE _ATTRIBUTE_CACHE_MAXSIZE = settings.ATTRIBUTE_CACHE_MAXSIZE
def test():
print "Called: %s " % time()
class ExtendedLoopingCall(LoopingCall):
"""
LoopingCall that can start at a delay different
than self.interval.
"""
start_delay = None
def start(self, interval, now=True, start_delay=None):
"""
Start running function every interval seconds.
This overloads the LoopingCall default by offering
the start_delay keyword.
start_delay: The number of seconds before starting.
If None, wait interval seconds. Only
valid is now is False.
"""
assert not self.running, ("Tried to start an already running "
"LoopingCall.")
if interval < 0:
raise ValueError, "interval must be >= 0"
self.running = True
d = self.deferred = Deferred()
self.starttime = self.clock.seconds()
self._lastTime = self.starttime
self.interval = interval
if now:
self()
elif start_delay is not None and start_delay >= 0:
self.interval = start_delay
self._reschedule()
# this is set after the _reshedule call to make
# next_call find it until next reshedule.
self.start_delay = start_delay
self.interval = interval
else:
self._reschedule()
return d
def _reschedule(self):
"Handle delayed call so next_call get it right"
self.start_delay = None
super(ExtendedLoopingCall, self)._reschedule()
def reset(self, force_call=True):
"""
Reset the loop timer. The task must already be started.
force_call - trigger the callback function
"""
assert self.running, ("Tried to reset a LoopingCall that was "
"not running.")
if self.call is not None:
self.call.cancel()
if force_call:
self()
else:
self._reschedule()
def next_call_time(self):
"""
Return the time in seconds until the next call. This takes
start_delay into account.
"""
currentTime = self.clock.seconds()
if self.start_delay is not None:
# take start_delay into account
untilNextTime = (self._lastTime - currentTime) % self.start_delay
return max(self._lastTime + self.start_delay, currentTime + untilNextTime)
else:
untilNextTime = (self._lastTime - currentTime) % self.interval
return max(self._lastTime + self.interval, currentTime + untilNextTime)
# #
# Base script, inherit from Script below instead. # Base script, inherit from Script below instead.
# #