I have an ActiveMapper class which looks like this:

class OraJob(ActiveMapper):
    class mapping:
        id = column(Integer, primary_key = True)
        job_type = column(Unicode(30))
        source_type = column(Unicode(30))
        ...

Attributes are used / should be used in readonly manner. All updates to
database are happening via specialized Oracle procedures (that in turn
use AUTONOMOUS_TRANSACTION). This is so because changes to this object
must be committed to database no mater what is the outcome of main
transaction and must be written immediately so I can track the progress
of job from outside.

One of update functions looks like this:

    def start_job(self, status_message, expected_steps = None):
        self.status_message = status_message
        if expected_steps is not None:
            self.expected_steps = expected_steps
        orapro.tool_job.start_job( # This calls my Oracle function
start_job()
            i_job_id = self.id
           ,i_status_message = status_message
           ,i_expected_steps = expected_steps
        ).execute(connection())
        self.status = u"RUNNING"

My problem is in:

    self.status = something

because this causes the object to get dirty and it gets updated when I
flush the session. This sql update in turn locks the row, and my next
call to specialized update function (ie. finish_job) fails with a
deadlock (remember, specialized update is inside autonomous
transaction). My current solution is to expunge(self) when calling any
of specialized update functions:

    def finish_job(self, status_message, warnings, errors, extra =
None):
        self._expunge()
        if self.status != u'RUNNING':
            raise RuntimeError("You can only finish a job if it is in
RUNNING state.")
        self.status_message = status_message
        self.warnings = warnings
        self.errors = errors
        self.extra = extra
        orapro.tool_job.finish_job(
             i_job_id = self.id
            ,i_status_message = status_message
            ,i_warnings = warnings
            ,i_errors = errors
            ,i_extra = extra
        ).execute(connection())
        self.status = u"FINISHED"
    def _expunge(self):
        try:
            self.__expunged
        except AttributeError:
            session.expunge(self)
            self.__expunged = True

This barely works because currently I'm calling flush only *after* one
of my specialized update functions had a chance to expunge itself. My
next try was to create object with _sa_session=None...

How can I go about solving this problem:
1. somehow make attributes readonly for outside world but let me change
attributes from inside customized update function without affecting
dirty state
2. expunge object from session inside __init__ (if it is possible at
all)
3. expunge object from session on each call to update function
4. create object somehow so it doesn't end up inside session (is it
enough to say _sa_session=None when creating object)
5. something else

It seems that "readonly" attribute would be the best solution, because
the only interface for changing job state is through several well
defined functions (start/update/finish/fail)

Thanks,
Tvrtko


--~--~---------~--~----~------------~-------~--~----~
 You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
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
-~----------~----~----~----~------~----~------~--~---

Reply via email to