[PEAK] entityDM, Postgres/psycopg and cursors blocking each other

Phil Mayers p.mayers at imperial.ac.uk
Sat Sep 11 10:22:17 EDT 2004


All,

Doing a proof-of-concept in PEAK at the moment - very nice system.

I'm running into some behaviour specific to the psycopg Postgres DA, and 
it's connection pool. The problem is coming about because I'm using 3/4 
DMs that are apparently creating independent cursors, and at transaction 
commit time, the inserts/updates for one DM block on the previous 
selects of another DM (e.g. in the case of foreign keys).

class baseDM(storage.EntityDM):
    # Lots of interesting common code here
    # Is there an existing SQL reflector?

class Foo(model.Element):
    class fooid(model.Attribute):
	referencedType = model.String
    class foodescr(model.Attribute):
	referencedType = model.String

class FooDM(baseDM):
    # I'm sure this can be automated...
    defaultClass = Foo
    tablename = 'foo'
    primarykey = 'fooid'

class Bar(model.Element):
    class barid(model.Attribute):
	referencedType = model.String
    class fooid(model.Attribute):
	# Really, this should be:
	#   referencedType = Foo
	# ...but see below
	referencedType = model.String
    class installdate(model.Attribute):
	referencedType = model.String

class BarDM(baseDM):
    defaultClass = Bar
    tablename = 'bar'
    primarykey = 'barid'


...more code, then in the app:

for line in csv.reader(open(filename)):
    f = self.foodm.get(line['fooid'])
    if not f:
	f = self.foodm.newItem()
	f.fooid = line['fooid']
	f.description = line['description']
    else:
	if f.description!=line['description']:
	    # Is model.Element smart enough to ignore no-ops?
	    # Don't want redundant SQL
	    f.description=line['description']
    for b in line['bars'].split(':'):
	eb = self.bardm.get(b)
	if eb:
	    if eb.fooid!=f.fooid:
		print "Bar %s already assigned to %s" % (b, f.fooid)
	else:
	    eb = self.bardm.newItem()
	    eb.barid = b
	    eb.fooid = f.fooid

...however, when the transaction commits, the addition of the new "bar" 
fails, since the SQL INSERT waits on the "select * from foo where where 
fooid=xxx" that was done previously by the foo DM *in another cursor*.

What's the appropriate way to deal with many interacting DMs that share 
a connection but have differening cursors (and can potentially block 
each other)?

Also, as you can see above, there's a lot of manual code which I'm sure 
some hypothetical SQL reflector could do automatically? Has this been 
done, or should I write it (I need it, and it's not too hard)? If I 
write it, would people be interested in having it added to PEAK? What's 
the licensing / code style / etc.

-- 

Regards,
Phil

+------------------------------------------+
| Phil Mayers                              |
| Network & Infrastructure Group           |
| Information & Communication Technologies |
| Imperial College                         |
+------------------------------------------+



More information about the PEAK mailing list