persistent background process

123 views
Skip to first unread message

Auden RovelleQuartz

unread,
Dec 29, 2009, 11:26:38 PM12/29/09
to web2py-users, omni...@yahoo.com, dsl...@gmail.com
any simple example on how to create a persistent background process
that runs continuously on the server side no matter what user signs in
or out, and no matter how many concurrent users are on the system?

Here are a couple of examples:

when a user performs an "event", it kicks off a server side process
that continues executing even when that user signs off.

when a user performs an "event", then after a set period of time (say
two days) then an email is automatically sent to a specified e-mail
address that happens even if the user that triggers the event no
longer has an active session on the server side.

I am attempting to build an auction application in the web2py
framework and would be interested in learning a tecqnique of starting
(and stopping) persistent server-side background processes.

Much thanks

Richard

unread,
Jan 3, 2010, 8:28:52 AM1/3/10
to web2py-users
I haven't implemented this yet, but my plan on Linux to keep a
background process running is:

- Define a task table, which is checked on every request
- If the task table is empty then start the background task with
subprocess and store the pid in the task table
- If the task table has an entry but its pid is not active (not in /
proc) then restart the background task and update the pid
- Else the task is running fine

Perhaps you could adapt that to your needs, assuming you are using
Linux.

Richard


On Dec 30 2009, 3:26 pm, Auden RovelleQuartz <oves....@gmail.com>
wrote:

mdipierro

unread,
Jan 3, 2010, 11:06:13 AM1/3/10
to web2py-users
This is what I would do:

db.define_table('queue',Field('status'),Field('descr'))

In actions

db.queue.insert(status='PENDING',descr='whatever')

In your own scrips that you can run via CRON or via background process

while True:
tasks = db(db.queue.status=='PENDING').select(limitby=(0,10)).first
()
if task:
task.update_record(status='PROCESSING')
db.commit()
try:
#process task
task.update_record(status='COMPLETED')
except:
task.update_record(status='FAILED')
db.commit()
else:
sleep(10) # retry in 10 seconds

Michael Toomim

unread,
Jan 3, 2010, 12:58:42 PM1/3/10
to web2py-users
Great! I am also trying to implement this. Richard and Auden, have
you gotten anything working yet? How about we share solutions?

My current difficulty is figuring out where to create the persistent
background thread.
- If I spawn it in a controller or model file will it be limited to
10 seconds?
- If I run it in a periodic cron there will be a delay and I will
need to handle the case of multiple threads running simultaneously
- If I use @reboot cron, it prevents web2py from shutting down (it
seems to wait for my thread to quit, which does not know to quit)

Any ideas on these problems? It would be great to have a general task
queue in web2py, like the one on GAE. Although I've never learned how
to use the GAE one, perhaps what we're making could be easier to use.

mdipierro

unread,
Jan 3, 2010, 1:23:12 PM1/3/10
to web2py-users
I normally just start a separate web2py process.

python web2py.py -S app -M -S thescript

> > > > Much thanks- Hide quoted text -
>
> - Show quoted text -

Richard

unread,
Jan 3, 2010, 4:57:33 PM1/3/10
to web2py-users
I was doing that but sometimes the process crashed or was killed by my
hosting provider, so I need a way to continue it automatically. Also I
may want to execute a number of background tasks in parallel. And it
uses extra resources that aren't needed, which is a problem on my
hosting where I am reaching the limits.

Michael, are you looking for a particular platform solution or cross
platform?

Michael Toomim

unread,
Feb 26, 2010, 5:05:51 PM2/26/10
to web2py-users
I got this to work by using @reboot cron. It works great, and super
simple. Cross-platform, needs no external daemons.

The trick was that web2py wasn't shutting down when my script was
running, because I had a try-catch that was catching the
KeyboardInterrupt exception. So here's what I did:

In cron/crontab:

@reboot toomim *applications/init/cron/background_work.py

(Thanks to achipa and massimo for fixing @reboot recently!)
In cron/background_work.py:

import time, sys, commands, datetime

# Lock the database so we don't accidentally run two background
# processes at the same time, e.g. if we run web2py twice by
accident
if not db.executesql('select pg_try_advisory_lock(1);')[0][0]:
logging.debug('CRON: FAILED to get background process lock')
raise Exception('Somebody else is running background
processes')
logging.debug('CRON: got lock')


count = 0
while True:
count += 1
logging.debug('Sleeping for the %dth time' % count)
time.sleep(10)
try:
logging.debug('Processing launch queue')
process_launch_queue()
logging.debug('Processing bonus queue')
process_bonus_queue()
except KeyboardInterrupt as e:
logging.debug('Someone killed us.')
raise
except:
logging.debug("Error in background process: %s" %
sys.exc_info()[0])

Note that I explicitly catch the KeyboardInterrupt and re-raise it so
the script dies. If you kill web2py with some other type of exception
you might need to put it in there too.

The other trick is that print statements and exceptions aren't
displayed at the console because this is run as a separate python
process. So you need to use logging.debug from log.py. I don't
remember where I got that file...

> > > > > > any simple example on how to create apersistentbackground process


> > > > > > that runs continuously on the server side no matter what user signs in
> > > > > > or out, and no matter how many concurrent users are on the system?
>
> > > > > > Here are a couple of examples:
>
> > > > > > when a user performs an "event", it kicks off a server side process
> > > > > > that continues executing even when that user signs off.
>
> > > > > > when a user performs an "event", then after a set period of time (say
> > > > > > two days) then an email is automatically sent to a specified e-mail
> > > > > > address that happens even if the user that triggers the event no
> > > > > > longer has an active session on the server side.
>
> > > > > > I am attempting to build an auction application in the web2py
> > > > > > framework and would be interested in learning a tecqnique of starting

> > > > > > (and stopping)persistentserver-side background processes.

Michael Toomim

unread,
Feb 26, 2010, 5:07:19 PM2/26/10
to web2py-users
Oh yeah, and that database lock line only works with postgresql. You
might try file locking if you're not using it.
Reply all
Reply to author
Forward
0 new messages