Sunday, August 21, 2011

Hidden threat in Storm's __storm_pre_flush()

Here at Cogini, we have an internal framework named Warp which uses Storm for ORM. Besides the fact that there is little document for the ORM (and only a fraction of that little is useful), there are also a number of tricks that make you simply want to tear your hair off. Below is one of those.

Preface: Storm's Store is the highest-level interface to a database. In Storm, every change to the database is put into transaction with commit and rollback. The story invovles Store's find() and Storm's base class' __storm_pre_flush__()
  • find(): perform high-level querying
  • __storm_pre_flush()__: executed before the object is flushed

I had two classes, everytime they were saved, they removed all the old entries before adding the new ones.

And I kept receiving this error: psycopg2.IntegrityError: duplicate key value violates unique constraint "student_intended_course_student_id_key" for line 14

StudentStudyPlan absolutely had nothing to do with StudentIntendedCourses, how come the error was fired here?
Whenever Store's find() is called, it triggers a flush so that newly added entries (not in the database yet as the transaction might have not been committed) wont be omitted. And right before Student object is flushed, it's __storm_pre_flushed__ is called.
Unfortunately inside _determineStatus(), implicit find() is used. This totally messed up the transactions and gave me the error mentioned earlier.

The solution is to move into __storm_flushed__ (called after the flush is done). Check if the status is changed, if so update it and commit.

A dirty trick, but still good to know if you want to both work with Storm and avoid being bald before your thirties!

1 comment: