1
# JobInterval scheduler
2
# (c) Wijnand 'tehmaze' Modderman - http://tehmaze.com
5
from gozerbot.generic import calledfrom, lockdec, rlog, strtotime, \
7
import gozerbot.thr as thr
14
plock = thread.allocate_lock()
15
locked = lockdec(plock)
18
class JobError(Exception):
20
""" job error exception """
26
""" job to be scheduled """
40
def member(self, group):
41
""" check for group membership """
42
return self.group == group
46
""" job to run at a specific time/interval/repeat """
48
def __init__(self, start, interval, repeat, func, *args, **kw):
56
if type(start) in [types.IntType, types.FloatType]:
57
self.next = float(start)
58
elif type(start) in [types.StringType, types.UnicodeType]:
60
if d and d > time.time():
63
raise JobError("invalid date/time")
64
if type(interval) in [types.IntType]:
65
d = datetime.timedelta(days=interval)
66
self.delta = d.seconds
71
return '<JobAt instance next=%s, interval=%s, repeat=%d, function=%s>' % (str(self.next),
72
str(self.delta), self.repeat, str(self.func))
75
""" run check to see if job needs to be scheduled """
76
if self.next <= time.time():
77
rlog(-15, 'periodical', 'running %s' % str(self.func))
78
self.func(*self.args, **self.kw)
79
self.next += self.delta
81
if self.repeat > 0 and self.counts >= self.repeat:
82
return False # remove this job
85
class JobInterval(Job):
87
""" job to be scheduled at certain interval """
89
def __init__(self, interval, repeat, func, *args, **kw):
94
self.repeat = int(repeat)
96
self.interval = float(interval)
98
self.next = time.time() + self.interval
100
rlog(5, 'periodical', 'scheduled next run of %s in %d seconds' % \
101
(str(self.func), self.interval))
104
return '<JobInterval instance next=%s, interval=%s, repeat=%d, group=%s, \
105
function=%s>' % (str(self.next), str(self.interval), self.repeat, self.group,
109
""" run check to see if job needs to be scheduled """
110
if self.next <= time.time():
111
rlog(-15, 'periodical', 'running %s' % (str(self.func)))
112
self.next = time.time() + self.interval
114
self.func(*self.args, **self.kw)
115
except Exception, ex:
118
if self.repeat > 0 and self.counts >= self.repeat:
119
return False # remove this job
122
class Periodical(object):
124
""" periodical scheduler """
126
SLEEPTIME = 1 # smallest interval possible
131
thr.start_new_thread(self.checkloop, ())
133
def addjob(self, sleeptime, repeat, function, description="" , *args, **kw):
134
job = JobInterval(sleeptime, repeat, function, *args, **kw)
135
job.group = calledfrom(sys._getframe())
136
job.description = str(description)
137
self.jobs.append(job)
140
def changeinterval(self, pid, interval):
141
for i in periodical.jobs:
143
i.interval = interval
144
i.next = time.time() + interval
149
for job in self.jobs:
150
if job.next <= time.time():
151
thr.start_new_thread(self.runjob, (job, ))
153
time.sleep(self.SLEEPTIME)
155
def runjob(self, job):
156
""" kill job is not to be runned """
158
self.killjob(job.id())
161
''' kill all jobs invoked by another module '''
162
group = calledfrom(sys._getframe())
163
self.killgroup(group)
165
def killgroup(self, group):
166
''' kill all jobs with the same group '''
169
""" knock down all jobs belonging to group """
170
deljobs = [job for job in self.jobs if job.member(group)]
172
self.jobs.remove(job)
173
rlog(10, 'periodical', 'killed %d jobs for %s' % (len(deljobs), \
176
shoot() # *pow* you're dead ;)
178
def killjob(self, jobId):
179
''' kill one job by its id '''
182
deljobs = [x for x in self.jobs if x.id() == jobId]
183
numjobs = len(deljobs)
185
self.jobs.remove(job)
188
return shoot() # *pow* you're dead ;)
190
periodical = Periodical()
192
def interval(sleeptime, repeat=0):
193
""" interval decorator """
194
group = calledfrom(sys._getframe())
195
def decorator(function):
196
decorator.func_dict = function.func_dict
197
def wrapper(*args, **kw):
198
job = JobInterval(sleeptime, repeat, function, *args, **kw)
200
periodical.jobs.append(job)
201
rlog(5, 'periodical', 'new interval job %d with sleeptime %d' % \
202
(job.id(), sleeptime))
206
def at(start, interval=1, repeat=1):
208
group = calledfrom(sys._getframe())
209
def decorator(function):
210
decorator.func_dict = function.func_dict
211
def wrapper(*args, **kw):
212
job = JobAt(start, interval, repeat, function, *args, **kw)
214
periodical.jobs.append(job)
215
wrapper.func_dict = function.func_dict
219
def minutely(function):
220
""" minute decorator """
221
minutely.func_dict = function.func_dict
222
group = calledfrom(sys._getframe())
223
def wrapper(*args, **kw):
224
job = JobInterval(60, 0, function, *args, **kw)
226
periodical.jobs.append(job)
227
rlog(5, 'periodical', 'new interval job %d running minutely' % \
231
def hourly(function):
232
""" hour decorator """
233
rlog(0, 'periodical', '@hourly(%s)' % str(function))
234
hourly.func_dict = function.func_dict
235
group = calledfrom(sys._getframe())
236
def wrapper(*args, **kw):
237
job = JobInterval(3600, 0, function, *args, **kw)
239
rlog(5, 'periodical', 'new interval job %d running hourly' % job.id())
240
periodical.jobs.append(job)
244
""" day decorator """
245
rlog(0, 'periodical', '@daily(%s)' % str(function))
246
daily.func_dict = function.func_dict
247
group = calledfrom(sys._getframe())
248
def wrapper(*args, **kw):
249
job = JobInterval(86400, 0, function, *args, **kw)
251
periodical.jobs.append(job)
252
rlog(5, 'periodical', 'new interval job %d running daily' % job.id())