lets see if i understand u correctly, as i have quite similar situation (ERP server which should keep users access-control info cached). Although i dont have lazy-loading of stuff now, i may need it one day.
so, u want to have one (global) cached tree where one thread may write to it as requested (semaphored), and many threads may only query the tree in a way or another but do not write to it, right? if not, can u explain it in such non-app-specific terms? one way i see is to have one thread that contains the tree privately and behaves like a mediator/server, and all other threads are client to it, asking for queries or writes. but this is only if i understood it right. svil On Saturday 28 July 2007 21:25:47 MuTPu4 wrote: > On Jul 28, 5:36 pm, Michael Bayer <[EMAIL PROTECTED]> wrote: > > your best option is probably to keep the objects in a session > > that's specifically for the "global" objects. Most important is > > that if you are using multiple threads, you never call flush() on > > this session. With regards to threadsafety in this case, as long > > as the session is not used for a flush() operation, you should be > > OK. The connection used for querying for a non-transactional > > session is checked out distinctly per-operation, so there will be > > no conflicts there. The second place of concern is when the > > Query retrieves existing objects from the identity map as it > > loads rows, and as it places newly loaded objects into the > > identity map; multiple threads might both create the same object > > and might both store it in the identity map; only one would > > actually remain in the map. However for a purely read-only > > situation, your application will still see the same kinds of > > objects, and even the object that was "replaced", which still > > would remain established in a parent collection, can still call > > upon that session to issue further lazyloads. > > > > I might look into adding a flag in 0.4 session "readonly", which > > produces a session that disallows flush() and places a single > > mutex around query.instances(); then youd have a completely > > threadsafe read- only session. its only a couple of lines. > > Thanks for your replay. > Probably my case is somewhat more compilcated but I thought that it > is rather common. It may be outlined as follows. > I have a long-running application (web server) which resopnds to > frequent queries users (pages fetch). The data is organized into > hierarchical directory which is represented by Nodes and Items: > [code] > self.categories_table = Table( > 'categories' > , self.metadata > , Column( 'category_id', Integer, primary_key = True ) > , Column( 'name', String, nullable = False, index = True ) > , Column( 'parent_category_id', Integer, nullable = True, > index = True ) > > , ForeignKeyConstraint( [ 'parent_category_id' ], > [ 'categories.category_id' ], onupdate = 'CASCADE', ondelete = > 'CASCADE' ) > ) > self.items_table = Table( > 'items' > , self.metadata > , Column( 'item_id', Integer, primary_key = True ) > , Column( 'name', String, nullable = False, index = True ) > , Column( 'parent_category_id', Integer, nullable = False, > index = True ) > > , ForeignKeyConstraint( [ 'parent_category_id' ], > [ 'categories.category_id' ], onupdate = 'CASCADE', ondelete = > 'CASCADE' ) > ) > [/code] > I want to have a global preloaded tree structure for fast access > (frequent reads and infrequent modifications) with application's > lifetime and ability to fetch Items as needed. I wanted to use some > nice automation features of SA's ORM (lazy > loads across relations, automatic DB updates etc) so I have come up > with the following "solution": > [code] > class Category( object ) : > def __init__( self, name, parent_category ) : > self.name = name > self.parent = parent_category > > class Item( object ) : > def __init__( self, name, parent_category ) : > self.name = name > self.parent = parent_category > [/code] > [code] > #data mapping > self.items_mapper = mapper( item.Item, self.items_table, > properties = { > 'parent' : relation( Category, uselist = False, lazy = > False ) } ) > self.categories_mapper = mapper( category.Category, > self.categories_table, properties = { > 'children' : relation( Category, backref = backref( > 'parent', remote_side = [ self.categories_table.c.category_id ] ), > cascade = 'all' ) > } ) > [/code] > [code] > #application init > session = self.db.create_session( ) > self.root = > session.query( Category ).selectone( Category.c.parent_category_id > == None ) > session.close( ) > [/code] > [code] > #hypothetical code in one of the threads > session = self.db.create_session( ) > new_obj = Category( 'test', directory.root ) > session.save( new_obj ) > session.flush( ) > print new_obj.parent.name > len( new_obj.children ) > subitems = session.query( Item ).select_by( parent_category_id = > directory.root.category_id ) > session.close( ) > [/code] > Now I see that this approach is not viable as-is. Maybe there is a > way to adopt it using modules like SessionContext and assignmapper? > If there is no such a way, I currently see two solutions: > 1. Just dont use permanent objects and fetch an appropriate > portions of informations at every request relaying on DB's cache > and loopback network optimizations. > 2. Using basic SA features implement an ad-hoc ORM as a part of > Category and Item classes which will use given session to > fetch/insert/ uopdate data. > Maybe someone can point me to another not so painful solution? > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---