scheduling one time tasks with tg.scheduler

3 views
Skip to first unread message

Karl Guertin

unread,
May 12, 2006, 7:18:50 PM5/12/06
to turbo...@googlegroups.com
I found that the scheduler is missing one piece of functionality that
I'd like. I currently have a datetime object and I want to run a given
action at the time specified by my object. To that end I've added the
following functionality to scheduler:

....def add_datetime_task(self, action, taskname, date_time,
processmethod, args, kw):
........"""Add a new task to the schedule. This provides a way to
generate one-time
........ events where you know the time you want the event to occur"""
........now = time.time()
........date_time = time.mktime(date_time.timetuple())
........if date_time - now < 0:
............return None
........if processmethod==method.sequential:
............TaskClass=OneTimeTask
........elif processmethod==method.threaded:
............TaskClass = ThreadedOneTimeTask
........elif processmethod = method.forked:
............TaskClass = ForkedOneTimeTask
........if not args:
............args = []
........if not kw:
............kw = {}
........task = TaskClass(taskname, date_time, action, args, kw)
........self.schedule_task_abs(task,date_time)
........return task

class OneTimeTask(Task):
....def __init__(self, name, date_time, action, args=None, kw=None):
........Task.__init__(self, name, action, args, kw)

....def reschedule(self, scheduler):
........pass


Along with the mixins and convenience function. It seems to work, but
before I shoot myself in the foot, will I have a problem with an
excessive number of threads?

It doesn't look like I get a thread for every datetime_task added but
my knowledge of the threading module is weak and I don't see the
scheduling threads ever dying.

Robin Haswell

unread,
May 12, 2006, 8:15:35 PM5/12/06
to turbo...@googlegroups.com
I actually opened a ticket on this today:

http://trac.turbogears.org/turbogears/ticket/867

-Rob

Tim Lesher

unread,
May 12, 2006, 8:54:46 PM5/12/06
to turbo...@googlegroups.com
On 5/12/06, Robin Haswell <r...@digital-crocus.com> wrote:
>
> I actually opened a ticket on this today:

You didn't mention it in your ticket, but what do you need that
threading.Thread doesn't provide?

--
Tim Lesher <tle...@gmail.com>

Robin Haswell

unread,
May 13, 2006, 6:13:14 AM5/13/06
to turbo...@googlegroups.com
And on a related note, what do widgets have that HTML and some if statements don't provide?

Creating a scheduled task is a lot easier than messing about creating your own class with a run()
instance etc.

-Rob

Jorge Godoy

unread,
May 13, 2006, 8:46:55 AM5/13/06
to turbo...@googlegroups.com
Em Sábado 13 Maio 2006 07:13, Robin Haswell escreveu:
> And on a related note, what do widgets have that HTML and some if
> statements don't provide?

Improved reusability, they make it easier to insert something on the page
since they carry their CSS + JS with them, validators can be specified inside
the widget, validators can be overriden in a form with a validation schema,
validators can be overriden in an exposed method with the validate decorator,
widgets separate logic from template, widgets can have their template changed
without changing their code, etc.


--
Jorge Godoy <jgo...@gmail.com>

Kevin Dangoor

unread,
May 13, 2006, 1:55:58 PM5/13/06
to turbo...@googlegroups.com
Hi Karl,

I knew this was going to come up when I added the scheduler, but I
didn't want to do anything about it right then. Thanks for doing the
work for me!

Off the top of my head, the code looks fine. The scheduler itself only
uses one thread no matter how many jobs you have scheduled. The
threads for the scheduled jobs *should* terminate when the job is
done.

Kevin

Tim Lesher

unread,
May 14, 2006, 12:35:36 AM5/14/06
to turbo...@googlegroups.com
On 5/13/06, Robin Haswell <r...@digital-crocus.com> wrote:
>
> And on a related note, what do widgets have that HTML and some if statements don't provide?
>
> Creating a scheduled task is a lot easier than messing about creating your own class with a run()
> instance etc.

I wasn't being sarcastic at all. I was actually curious.

Incidentally, you don't have to derive a class to use threading--you
can do it in one line:

threading.Thread(target=my_function, args=(arg1,arg2)).start()

Using the scheduler for a one-shot, deferred call just seems like the
long way around to me.
--
Tim Lesher <tle...@gmail.com>

Kevin Dangoor

unread,
May 15, 2006, 8:04:04 AM5/15/06
to turbo...@googlegroups.com
On 5/14/06, Tim Lesher <tle...@gmail.com> wrote:
> Using the scheduler for a one-shot, deferred call just seems like the
> long way around to me.

There's no plus to the scheduler if you're just looking to get a task
going in the background now. However, if you want the task to run at
another time, the advantage to the scheduler is that it uses only one
thread no matter how many tasks you've got queued up.

It also has the added bonus that you can change one function parameter
to use a new process instead of a new thread (which can be very
important on a multiprocessor machine).

Kevin

Tim Lesher

unread,
May 15, 2006, 10:12:17 AM5/15/06
to turbo...@googlegroups.com
On 5/15/06, Kevin Dangoor <dan...@gmail.com> wrote:
>
> On 5/14/06, Tim Lesher <tle...@gmail.com> wrote:
> > Using the scheduler for a one-shot, deferred call just seems like the
> > long way around to me.
>
> There's no plus to the scheduler if you're just looking to get a task
> going in the background now. However, if you want the task to run at
> another time, the advantage to the scheduler is that it uses only one
> thread no matter how many tasks you've got queued up.

I agree with that; the ticket Robin submitted didn't mention running
the task at a specific time, though. If that's what he meant, I
apologize.
--
Tim Lesher <tle...@gmail.com>

Robin Haswell

unread,
May 16, 2006, 11:07:21 AM5/16/06
to turbo...@googlegroups.com
Tim Lesher wrote:
> I agree with that; the ticket Robin submitted didn't mention running
> the task at a specific time, though. If that's what he meant, I
> apologize.

In which case I apologize for being unclear - that is what I meant,
however I also see the use in being able to use the scheduler to run a
background task now - for these reasons:

1. It's the same API for two essentially identical tasks
2. Threading/forking is scary for n00bs - I dunno how TG does it, but I
know I would be worried about forking or threading a webserver, because
forking it is going to leave two copies in memory, and threading while a
DB connection is open brings back scary nightmares from projects past. I
would much rather leave it to a tested API.

Regardless of that though, I think scheduling a one-time task is a good
idea IMO. In at least one of my TG apps I need to perform an action in
24 hours' time (although I don't use the TG scheduler for that as I
don't trust the server to run for 24 hours without crashing).

-Rob

Jorge Godoy

unread,
May 16, 2006, 11:22:34 AM5/16/06
to turbo...@googlegroups.com
Em Terça 16 Maio 2006 12:07, Robin Haswell escreveu:

> Regardless of that though, I think scheduling a one-time task is a good
> idea IMO. In at least one of my TG apps I need to perform an action in
> 24 hours' time (although I don't use the TG scheduler for that as I
> don't trust the server to run for 24 hours without crashing).

You don't trust the hardware or the software? I have stable websites with TG
running non-stop here. All with an Apache proxying requests to CP.

But, I also rely on cron for automated repetitive tasks. A scheduler would be
more for sporadic things or to allow users scheduling some maintenance
routines (I can create crontab entries for those, though...).

--
Jorge Godoy <jgo...@gmail.com>

Robin Haswell

unread,
May 16, 2006, 11:54:05 AM5/16/06
to turbo...@googlegroups.com
The software, based on my development experiences. That and if I want to
change a character of code I have to restart the server - and scheduler.

-Rob

Jorge Vargas

unread,
May 16, 2006, 2:41:39 PM5/16/06
to turbo...@googlegroups.com
I'm looking at the internals of this I I believe sending in interval=0 will do a one-time task

Looking all the way into the sched.py module you will see the sheduler class enter and enterabs, so 0 will make both functions "equal"

then you will see in the run method it just get call

that will be calling

add_interval_task(action,0)

Can someone with a co test this?

On 5/12/06, Karl Guertin <gray...@gmail.com> wrote:

Kevin Dangoor

unread,
May 17, 2006, 8:19:30 AM5/17/06
to turbo...@googlegroups.com
On 5/16/06, Jorge Vargas <jorge....@gmail.com> wrote:
> I'm looking at the internals of this I I believe sending in interval=0 will
> do a one-time task

The problem is the IntervalTask class itself:

class IntervalTask(Task):
"""A repeated task that occurs at certain intervals (in seconds)."""
def __init__(self, name, interval, action, args=None, kw=None):
Task.__init__(self, name, action, args, kw)
self.interval=interval

def reschedule(self, scheduler):
# reschedule this task according to its interval (in seconds).
scheduler.schedule_task(self, self.interval)


reschedule will run it again immediately.

Kevin

Reply all
Reply to author
Forward
0 new messages