the message you're getting is due to an exception being raised,but
rollback() not being called on the session. When you catch those
ConcurrentModification exceptions, you have to issue a rollback().
I dont see anything else with the code that would suggest the same row
being deleted in two places, although it does seem like theres likely
a more succinct way of structuring that code, and I also dont see the
purpose that the session.expire_all() accomplishes. Things missing
here include what scope is the session managed under (i.e. where is it
created/destroyed/shared among threads) as well as what other
concurrency exists within this section of the application.
On Oct 27, 2008, at 9:15 PM, Doug Farrell wrote:
>
> Hi all,
>
> I'm using Python 2.5.1 with SqlAlchemy 0.5rc2 with Sqlite on Windows
> Server 2003 and I'm having a problem with my application throwing
> InvalidRequestError and ConcurrentModification exceptions. Here is my
> simplified declarative class:
>
> class Job(srsmanagerdb.Base):
> STATUS_INIT = 0
> STATUS_RUN = 1
> STATUS_DONE = 2
> STATUS_FAIL = 3
> __tablename__ = "jobs"
> id = Column(Integer, primary_key=True,
> autoincrement=True)
> nas = Column(String(12), default=None)
> filename = Column(String(64), default=None, index=True)
> filesize = Column(Integer, default=None)
> created = Column(DateTime, default=None)
> job_id = Column(String(32), default=None)
> productType = Column(String(1), default=None)
> contentType = Column(String(10), default=None)
> priorityType = Column(String(10), default=None)
> priority = Column(Integer, default=None)
> assignedPress = Column(Integer, default=None)
> status = Column(Integer, default=None)
>
> def __init__(self, objrefs, fileDetails):
> nas, filename, filesize, ctime = fileDetails
> self.nas = nas
> self.filename = filename
> self.filesize = filesize
> self.created =
> datetime.datetime(*time.strptime(ctime[:ctime.find(".")], "%Y-%m-%d
> %H:%M:%S")[0:6])
>
> This object is used to track state information about jobs being
> handled
> by a looping state machine. I keep a list of all active jobs in a Jobs
> collection class, so there are many active intances of the above
> class.
> The simplified Jobs collection class looks like this:
>
> class Jobs(AppContext):
> def __init__(self, objrefs):
> self._logger = __logger__
> self._jobs = []
> self._markedForRemoval = []
> def markForRemoval(self, job):
> self._markedForRemoval.append(job)
> def removeMarkedJobs(self): # throws exception in
> here
> session = srsmanagerdb.Session()
> for markedJob in self._markedForRemoval:
> try:
> session.expire_all()
> session.delete(markedJob)
> session.commit()
> self._jobs.remove(markedJob)
> except sqlalchemy.exceptions.ConcurrentModificationError,
> e:
> self._logger.warn("%s threw exception %s" %
> (job.filename, e))
> self._markedForRemoval = []
> def process(self):
> for job for self._jobs:
> job.process()
> if job.status == Job.STATUS_DONE:
> self.markForRemoval(job)
> self.removeMarkedJobs()
>
> The above simplified code runs for awhile (10s of minutes) with
> hundreds
> of jobs and then it throws the exception below in the
> removeMarkedJobs()
> method. I've worked really hard trying to figure out what's going
> wrong
> here. This is the only place where I delete jobs and commit that
> delete
> to the database. One question I have is if it's a good idea to keep a
> list of active Job instances (database rows) in a Python list. In my
> removeMarkedJobs() I'm deleting the job instances, and then removing
> the
> job instance from the list. Is this necessary or good practice? I
> haven't figured out if just deleting the job instance from the list
> (self._jobs.remove(markedJob)) will also delete the job from the
> database or not. Anyway, here's the traceback of the exception I'm
> getting. Any help would be appreciated.
>
> Thanks, Doug
>
> 2008-10-27 18:15:54 srsmanager ERROR unexpected error,
> restarting:
> Traceback (most recent call last):
> File "c:\cygwin\home\ripadmin\dev\srsmanager\srsprocess.py", line 154,
> in runjobs isActive = self._jobs.process()
> File "c:\cygwin\home\ripadmin\dev\srsmanager\jobs.py", line 436, in
> process self.removeMarkedJobs()
> File "c:\cygwin\home\ripadmin\dev\srsmanager\jobs.py", line 397, in
> removeMarkedJobs self._logger.warn("%s threw exception %s" %
> (markedJob.filename, e))
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\attributes.py", line 135, in __get__ return
> self.impl.get(instance_state(instance))
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\attributes.py", line 327, in get value = callable_()
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\attributes.py", line 909, in __call__ attr.impl.key in
> unmodified
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\mapper.py", line 1715, in _load_scalar_attributes result =
> session.query(mapper)._get(identity_key, refresh_state=state,
> only_load_props=attribute_names)
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\query.py", line 1211, in _get return q.all()[0]
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\query.py", line 985, in all return list(self)
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\query.py", line 1073, in __iter__ return
> self._execute_and_instances(context)
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\query.py", line 1076, in _execute_and_instances result =
> self.session.execute(querycontext.statement, params=self._params,
> mapper=self._mapper_zero_or_none(), _state=self._refresh_state)
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\session.py", line 750, in execute return
> self.__connection(engine, close_with_result=True).execute( File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\session.py", line 717, in __connection return
> self.transaction._connection_for_bind(engine)
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\session.py", line 309, in _connection_for_bind
> self._assert_is_active()
> File
> "c:\python\2.5\lib\site-packages\SQLAlchemy-0.5.0rc1-py2.5.egg
> \sqlalchem
> y\orm\session.py", line 244, in _assert_is_active "The transaction
> is inactive due to a rollback in a " InvalidRequestError: The
> transaction is inactive due to a rollback in a subtransaction. Issue
> rollback() to cancel the transaction
>
> >
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---