[ZODB-Dev] zodb wants to import my module?

Tim Peters tim at zope.com
Thu Nov 11 11:20:40 EST 2004


[Jeremy Hylton]
> It should also work fine if you don't have the code on the server. ZEO
> should raise that exception for a class exactly once in the process's
> lifetime.  It's trying to discover if the class has a conflict resolution
> method that the server should run.

I expect you're thinking here of tryToResolveConflict()'s ``_unresolvable``
cache of classes lacking conflict resolution methods, and are also thinking
here that a *log* message about "Unable to load class" is produced at most
once per class.

But none of that's relevant here:  the problem is in
ConflictError.__init__():

                if serial != cached_tid:
                    rdata = self.tryToResolveConflict(oid, cached_tid,
                                                     serial, data)
                    if rdata is None:
                        raise POSException.ConflictError(
                            oid=oid, serials=(cached_tid, serial),
                            data=data)  # HERE
                    else:
                        data = rdata

*Every* time we try to raise ConflictError for an object of an application
class, where the application code isn't present, the exception's constructor
tries to load the first half of the ``data`` pickle, and so gets an
ImportError every time.  This code was new in 3.3, and has the consequence
Chris reported:  the ZEO client (re)raises the ImportError the server got
while trying to build a ConflictError exception.  tryToResolveConflict's
cache's only effect here is, in effect, to raise ImportError a little
quicker after the first time it's raised <wink>.

This is fixed on 3.3 branch now, and will be fixed soon on the trunk.

> (We've talked many times about changing the mechanism ZEO uses so
> that you can explicitly configure callables to run on conflicts for a
> particuar class.  There's no good reason to make them methods, and it
> causes some problems.)

I look forward to your patch <wink>.

> It can occasionally be bad to have client code on the server.  The
> problem is that the client code actually gets executed :-).  If the
> client code expects to be running inside of Zope, it can actually start
> to bring up Zope within the ZEO server.  That's very bad.  In general, if
> the code has side-effects at import time, you want to think carefully
> about whether you want those side-effects to occur on your ZEO server.

"The fix" here consisted of having the ConflictError constructor use
get_pickle_metadata() to get the class path instead of actually loading the
first half of the ZODB pickle.  God only knows if get_pickle_metadata() does
a right thing in all cases, but there's no other way to proceed.  There are
no known cases now in which get_pickle_metadata() will try to import modules
or classes (one case in which it did has been repaired since you were here).



More information about the ZODB-Dev mailing list