Zope, and hence Grok, is a multithreaded server.  This means that several requests may be served concurrently at any given time.  Where it comes to persistent data stored in the ZODB, it is possible that two different threads might modify the same ZODB object at the same time.

If this happens, we say there has been a conflict error. To handle this, Zope allows the one thread to succeed, and for the other thread, raises a ConflictError.

Handling Conflicts with ZoDB

The Zope 2 book demonstrates how to handle ZoDB conflicts with the following code, copied for your convenience:

class Counter(Persistent):

    self.count = 0

    def hit(self):
        self.count = self.count + 1

    def _p_resolveConflict(self, oldState, savedState, newState):

        # Figure out how each state is different:
        savedDiff= savedState['count'] - oldState['count']
        newDiff= newState['count']- oldState['count']

        # Apply both sets of changes to old state:
        oldState['count'] = oldState['count'] + savedDiff + newDiff

        return oldState

One would very seldom need to do this.

The _p_resolveconflict() method defined for the persistent class will be called if it exists, passing the original state prior to any changes, the saved state containing the changes made by the other thread, and the new state containing changes made by this thread.  The return value should be the merged state between savedState and newState.

Other conflicts

While Zope will handle most conflicts automatically, it is not able to handle concurrent access to external resources, and some libraries which depend on global objects or singletons might have difficulties.

For example, the MatPlotLib Python library which produces various graphs of sterling  quality is not thread safe.  Operations which use such resources should be serialised by means of a semaphore or similar mechanism.

Another way to deal with concurrency issues is by means of an event queue, which is a construct quite well supported by the Zope Component Architecture.

Grok 4 Noobs

Notes on multithreading