Thank.<div>That works.<br><br><div class="gmail_quote">On Mon, Jul 20, 2009 at 4:24 AM, Drew Smathers <span dir="ltr"><<a href="mailto:drew.smathers@gmail.com">drew.smathers@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5">On Fri, Jul 17, 2009 at 3:14 AM, Daniel<br>
Yang<<a href="mailto:daniel.yang.zhenyu@gmail.com">daniel.yang.zhenyu@gmail.com</a>> wrote:<br>
> Hi team,<br>
> I am doing some experiments on Storm(twisted integration) and Nevow to see<br>
> how they can work together.<br>
> I went across a RuntimeError when I kept refreshing a page. It said:<br>
> ------------------------------------------------log--------------------------------------------------------------<br>
> 2009-07-17 14:58:42+0800 [-] [Failure instance: Traceback: <type<br>
> 'exceptions.RuntimeError'>: Resolving lazy values with the Twisted wrapper<br>
> is not possible right now! Please refetch your object using<br>
> store.get/store.find<br>
> --- <exception caught here> ---<br>
> /Library/Python/2.5/site-packages/Twisted-8.2.0_r27097-py2.5-macosx-10.5-i386.egg/twisted/internet/defer.py:323:_runCallbacks<br>
> /Users/Daniel/Documents/workspace/NovaWeb/src/web/FromLocation.py:47:cb_all<br>
> /Library/Python/2.5/site-packages/storm-0.14-py2.5-macosx-10.5-i386.egg/storm/properties.py:60:__get__<br>
> /Library/Python/2.5/site-packages/storm-0.14-py2.5-macosx-10.5-i386.egg/storm/variables.py:178:get<br>
> /Library/Python/2.5/site-packages/storm-0.14-py2.5-macosx-10.5-i386.egg/storm/event.py:53:emit<br>
> /Library/Python/2.5/site-packages/storm-0.14-py2.5-macosx-10.5-i386.egg/storm/twisted/store.py:238:_resolve_lazy_value<br>
> ]<br>
> ------------------------------------------------log--------------------------------------------------------------<br>
> (latest storm and Nevow, Twisted.Python 2.5.1, Osx 10.5.7)<br>
> I am using StorePool to manage connections:<br>
> ------------------------------------------------code--------------------------------------------------------------<br>
><br>
> from storm.databases.sqlite import SQLite<br>
><br>
> from storm.uri import URI<br>
><br>
> from storm.twisted.store import StorePool<br>
><br>
> database = SQLite(URI('sqlite:///test.db'))<br>
><br>
> pool = StorePool(database, 5, 10)<br>
><br>
> pool.start()<br>
><br>
> ------------------------------------------------code--------------------------------------------------------------<br>
><br>
><br>
> On this page, I have 2 renders to access database(sqlite) with storm(People<br>
> list and Shop list):<br>
><br>
> ------------------------------------------------code--------------------------------------------------------------<br>
><br>
> def render_PeopleList(self, ctx, data):<br>
><br>
> pat = inevow.IQ(ctx).patternGenerator('PeopleItem')<br>
><br>
> def cb_find(results, s):<br>
><br>
> results.config(offset=0, limit=10)<br>
><br>
> return results.all().addCallback(cb_all, s)<br>
><br>
> def cb_all(items, s):<br>
><br>
> #recycle the store.<br>
><br>
> pool.put(s)<br>
><br>
> ps = []<br>
><br>
> for item in items:<br>
><br>
> p = pat()<br>
><br>
> p.fillSlots('nickname', item.nickname)<br>
><br>
> ps.append(p)<br>
><br>
> return ctx.tag[ ps ]<br>
><br>
> def cb_get(s):<br>
><br>
> return s.find(People).addBoth(cb_find, s)<br>
><br>
> return pool.get().addCallback(cb_get).addErrback(lambda error:<br>
> log.msg(error))<br>
><br>
> ------------------------------------------------code--------------------------------------------------------------<br>
> and shop render is pretty much like this.<br>
><br>
> In file "storm/twisted/store.py:238", I notice the _resolve_lazy_value<br>
> function does nothing but raising an error.<br>
> Do anyone have any idea of what is the problem?<br>
> Thanks.<br>
<br>
<br>
</div></div>This is the problem:<br>
<br>
pool.put(s)<br>
... doing something with object from store `s'<br>
<br>
Once you put a store back in the pool this will effectively rollback<br>
the store. Now being in a new transaction, referring to an attribute<br>
on the object will try to load the most recent data from the store to<br>
enforce "serializable" semantics. twisted-integration can't manage<br>
this because attribute access isn't can't be deferred in the store's<br>
thread -- without necessitating a very awkward API.<br>
<br>
I think some good practices to avoid lazy value errors are:<br>
<br>
1. Do everything you need to with objects before putting store back in<br>
pool and then discard those objects<br>
2. Re-fetch objects if you have done any inserts/updates (in same tx)<br>
before referencing attributes on them<br>
3. If you need to keep references lying around (caching as an<br>
example), create read-only version of those objects which aren't<br>
attached to store.<br>
<br>
Lastly, unrelated to you core problem, but this code looks like a unit<br>
test for twisted-integration. The tests are written to be compatible<br>
with older versions of Python, so you may consider using<br>
inlineCallbacks() to make your life easier if your deployment target<br>
is 2.5>. There is also a transact() method which takes care of<br>
putting the store back in pool after your function exits. An example<br>
using inlineCallbacks() and transact():<br>
<br>
from twisted.internet.defer import inlineCallbacks, returnValue<br>
<br>
@inlineCallbacks<br>
def transaction(store, offset, limit):<br>
dr = yield store.find(People)<br>
dr.config(offset=offset, limit=limit)<br>
items = yield dr.all()<br>
for item in items:<br>
... do stuff with item<br>
# commit tx if you've changed objects<br>
yield store.commit()<br>
returnValue(ctx_tag[ps])<br>
<br>
pool.transact(transaction, 0, 10)<br>
<br>
--<br>
\\\\\/\"/\\\\\\\\\\\<br>
\\\\/ // //\/\\\\\\\<br>
\\\/ \\// /\ \/\\\\<br>
\\/ /\/ / /\/ /\ \\\<br>
\/ / /\/ /\ /\\\ \\<br>
/ /\\\ /\\\ \\\\\/\<br>
\/\\\\\/\\\\\/\\\\\\<br>
d.p.s<br>
</blockquote></div><br><br clear="all"><br>-- <br>-----------------------------------------------<br>Yours<br>Faithfully<br><br>Daniel Yang<br>
</div>