Scheduler - Transaction Commit - Not Comitting

29 views
Skip to first unread message

Paul Kraus

unread,
May 3, 2011, 11:51:52 AM5/3/11
to TurboGears
In my scheduler i have some code that sets a flag on a database record
then remove its after the process is completed. During imports I
needed a way to have my app not allow some other actions to take
place. So i figure i would just write out a record to the DB that the
other code could test for when running. Seemed pretty straight
forward. If during the import the flag doesn't exist it also creates
it. Since I need to update the status right away i set the flag at the
beginning and do a transaction commit. This works. Then at the end i
set the value to 0 and commit again. It returns no errors but doesn't
update the DB.

def importOrders():

import_flag =
DBSession.query(Flag).filter(Flag.flag_name=='import_flag').first()
if not import_flag:
import_flag = Flag('import_flag')
DBSession.add(import_flag)

import_flag.flag_value = 1
transaction.commit()
... # Do stuff
import_flag.flag_value = 0
transaction.commit()

The flag will get created and always gets set to 1 but never gets set
to zero.

PK

Vince Spicer

unread,
May 3, 2011, 1:29:53 PM5/3/11
to turbo...@googlegroups.com
Tested and same behavior in shell, yeah an error would be nice but hard to catch.
 
try using DBSession.flush() in place of the commit and only commit once at the end of the scheduled method



--
You received this message because you are subscribed to the Google Groups "TurboGears" group.
To post to this group, send email to turbo...@googlegroups.com.
To unsubscribe from this group, send email to turbogears+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/turbogears?hl=en.




--
Vince Spicer


Paul Kraus

unread,
May 3, 2011, 1:46:25 PM5/3/11
to TurboGears
I had a similar thought but when I do DBSession.flush() in the
tgscheduler module it does nothing so then the initial add/set to 1
never happens. It seems that the only time it will actually write to
the DB is when transaction.commit() is called ignoring the flush.

Here is the entire module minus the extra "stuff"...

#!/usr/bin/env python
from tgscheduler import start_scheduler
import transaction
from tgscheduler.scheduler import add_interval_task, add_weekday_task,
add_single_task
import sys
import os
import logging
from datetime import datetime
from pel_pickship.model import DBSession
from pel_pickship.model.auth import Order, OrderLine, Flag
log = logging.getLogger(__name__)

def importOrders():
import_flag =
DBSession.query(Flag).filter(Flag.flag_name=='import_flag').first()
if not import_flag:
import_flag = Flag('import_flag')
DBSession.add(import_flag)

import_flag.flag_value = 1
transaction.commit()
.... #stuff
import_flag.flag_value = 0
transaction.commit()

def schedule():
""" start scheduler and setup recurring tasks """

if "shell" in sys.argv: # disable cron in paster shell mode
return

log.info("Starting Scheduler Manager")
start_scheduler()

#add_interval_task(action=importOrders, taskname="importOrders",
interval=5, initialdelay=0)
add_single_task(action=importOrders,initialdelay=0)

Christoph Zwerschke

unread,
May 3, 2011, 2:03:51 PM5/3/11
to turbo...@googlegroups.com
Am 03.05.2011 17:51 schrieb Paul Kraus:
> import_flag.flag_value = 1
> transaction.commit()
> ... # Do stuff
> import_flag.flag_value = 0
> transaction.commit()

You probably need to re-add import_flag to the session after the first
commit because it empties the session, i.e.

DBSession.add(import_flag)

Anyway, a semaphore or lock seems to be a better solution.

-- Christoph

Paul Kraus

unread,
May 3, 2011, 2:16:10 PM5/3/11
to TurboGears
That fixed my code and your right I was over thinking this, to much
coffee to little sleep.

Jasper

unread,
May 5, 2011, 8:23:25 AM5/5/11
to TurboGears
I have similar code in an "audit" decorator for exposed controller
methods (the audit decorator basically logs method calls along with
arguments and exceptions (if any) to a DB).
Note that in this scenario, one might need to reattach the user
identity to the session.

Paul Kraus

unread,
Jun 25, 2011, 5:22:18 PM6/25/11
to turbo...@googlegroups.com
Thread necromancy to help others if they come across this...

The semaphore and some other dirty hacks before the semaphore worked just fine. I was working on another issue with scheduler and was digging through the code and found that by passing in processmethod as method.sequential (have to from tgscheduler.kronos import method) it forces the task to only run sequentially. Since I wanted to prevent the task from firing before it had time to finish this was a more elegant solution.

To be clear the original question about "other tasks" correct answer was a semaphore but for the specific need of making sure the task only runs one at a time this was a good solution.

PK
Reply all
Reply to author
Forward
0 new messages