Commit ceadfcc7 authored by Kirill Smelkov's avatar Kirill Smelkov

lib/zodb: Teach Connection.onResyncCallback to work on ZODB4

In 959ae2d0 (lib/zodb: Add patch to ZODB.Connection to support callback
on connection DB view change) we added patch for ZODB.Connection to
support callback when database view of the connection changes. At that
time the patch was working for ZODB5 and ZODB4 was TODO.
Let's add support for ZODB4 (both ZODB4 and ZODB4-wc2) now.

As a reminder: ZBigFile + WCFS client integration will use this callback
to keep WCFS connection in sync with ZODB connection.

Preliminary history:

533a4cfa     X onResyncCallback for ZODB4
parent 23362204
...@@ -312,7 +312,6 @@ def test_zconn_at(): ...@@ -312,7 +312,6 @@ def test_zconn_at():
# verify that ZODB.Connection.onResyncCallback works # verify that ZODB.Connection.onResyncCallback works
@xfail(zmajor < 5, reason="ZODB.Connection.onResyncCallback is TODO for ZODB4")
@func @func
def test_zodb_onresync(): def test_zodb_onresync():
stor = testdb.getZODBStorage() stor = testdb.getZODBStorage()
......
...@@ -243,8 +243,6 @@ ZODB.Connection.Connection._onResyncCallbacks = None ...@@ -243,8 +243,6 @@ ZODB.Connection.Connection._onResyncCallbacks = None
def Connection_onResyncCallback(self, f): def Connection_onResyncCallback(self, f):
if zmajor <= 3: if zmajor <= 3:
raise AssertionError("onResyncCallback: ZODB3 is not supported anymore") raise AssertionError("onResyncCallback: ZODB3 is not supported anymore")
if zmajor == 4:
raise AssertionError("onResyncCallback: TODO: add support for ZODB4")
if self._onResyncCallbacks is None: if self._onResyncCallbacks is None:
# NOTE WeakSet does not work for bound methods - they are always created # NOTE WeakSet does not work for bound methods - they are always created
# anew for each obj.method access, and thus will go away almost immediately # anew for each obj.method access, and thus will go away almost immediately
...@@ -254,25 +252,43 @@ def Connection_onResyncCallback(self, f): ...@@ -254,25 +252,43 @@ def Connection_onResyncCallback(self, f):
assert not hasattr(ZODB.Connection.Connection, 'onResyncCallback') assert not hasattr(ZODB.Connection.Connection, 'onResyncCallback')
ZODB.Connection.Connection.onResyncCallback = Connection_onResyncCallback ZODB.Connection.Connection.onResyncCallback = Connection_onResyncCallback
def Connection__callResyncCallbacks(self):
# FIXME method name hardcoded. Better not do it and allow f to be general
# callable, but that does not work with bound method - see above.
# ( Something like WeakMethod from py3 could help )
if self._onResyncCallbacks:
for f in self._onResyncCallbacks:
f.on_connection_resync()
assert not hasattr(ZODB.Connection.Connection, '_callResyncCallbacks')
ZODB.Connection.Connection._callResyncCallbacks = Connection__callResyncCallbacks
# ZODB5: hook into Connection.newTransaction # ZODB5: hook into Connection.newTransaction
if zmajor >= 5: if zmajor >= 5:
_orig_Connection_newTransaction = ZODB.Connection.Connection.newTransaction _orig_Connection_newTransaction = ZODB.Connection.Connection.newTransaction
def _ZConnection_newTransaction(self, transaction, sync=True): def _ZConnection_newTransaction(self, transaction, sync=True):
_orig_Connection_newTransaction(self, transaction, sync) _orig_Connection_newTransaction(self, transaction, sync)
self._callResyncCallbacks()
# FIXME method name hardcoded. Better not do it and allow f to be general
# callable, but that does not work with bound method - see above.
# ( Something like WeakMethod from py3 could help )
if self._onResyncCallbacks:
for f in self._onResyncCallbacks:
f.on_connection_resync()
ZODB.Connection.Connection.newTransaction = _ZConnection_newTransaction ZODB.Connection.Connection.newTransaction = _ZConnection_newTransaction
# ZODB4: hook into Connection._storage_sync # ZODB4: hook into Connection._flush_invalidations and ._resetCache
elif zmajor == 4: elif zmajor == 4:
pass # raises in onResyncCallback # ._flush_invalidations is called by both Connection.open and Connection._storage_sync
# however Connection.open might call ._resetCache instead if global reset is requested
_orig_Connection__flush_invalidations = ZODB.Connection.Connection._flush_invalidations
_orig_Connection__resetCache = ZODB.Connection.Connection._resetCache
def _ZConnection__flush_invalidations(self):
_orig_Connection__flush_invalidations(self)
self._callResyncCallbacks()
def _ZConnection__resetCache(self):
_orig_Connection__resetCache(self)
self._callResyncCallbacks()
ZODB.Connection.Connection._flush_invalidations = _ZConnection__flush_invalidations
ZODB.Connection.Connection._resetCache = _ZConnection__resetCache
# ZODB3 # ZODB3
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment