1
# -*- test-case-name: axiom.test.test_scheduler -*-
2
from twisted.internet import reactor
4
from twisted.application.service import Service, IService
6
from axiom.item import Item
7
from axiom.attributes import timestamp, reference, text, integer, inmemory
8
from axiom.extime import Time
10
from axiom.slotmachine import Attribute
12
class TimedEvent(Item):
13
typeName = 'timed_event'
16
time = timestamp(indexed=True)
17
runnable = reference()
19
class Scheduler(Item, Service):
21
typeName = 'scheduler'
30
lastEventAt = timestamp()
31
nextEventAt = timestamp()
33
def __subinit__(self, **kw):
34
super(Scheduler, self).__subinit__(**kw)
38
def __init__(self, **kw):
39
super(Scheduler, self).__init__(**kw)
41
self.lastEventAt = None
42
self.nextEventAt = None
45
self.store.powerUp(self, IService)
51
def callLater(self, s, f, *a, **k):
52
s = max(s, 0.00000001)
53
return reactor.callLater(s, f, *a, **k)
59
self.nextEventAt = None
60
for event in self.store.query(TimedEvent,
61
TimedEvent.time < now,
62
sort=TimedEvent.time.ascending):
64
newTime = event.runnable.run()
65
if newTime is not None:
68
event.deleteFromStore()
71
self.lastEventAt = now
73
self.store.query(TimedEvent, sort=TimedEvent.time.ascending, limit=1))
76
self.timer = self.callLater(
77
x.time.asPOSIXTimestamp() - now.asPOSIXTimestamp(),
78
self.store.transact, self.tick)
79
self.nextEventAt = x.time
82
def schedule(self, runnable, when):
83
TimedEvent(store=self.store, time=when, runnable=runnable)
85
if self.timer is None:
86
self.timer = self.callLater(0.00001, self.store.transact, self.tick)
88
def startService(self):
89
super(Scheduler, self).startService()
90
self.store.transact(self.tick)
92
def stopService(self):
93
super(Scheduler, self).stopService()
94
if hasattr(self, 'timer'):