From 95a7530300aaba951df161d77bbc3fb228335f56 Mon Sep 17 00:00:00 2001
From: Julien Muchembled <jm@nexedi.com>
Date: Wed, 2 Dec 2020 16:37:48 +0100
Subject: [PATCH] Fix some monkey-patches to make them compatible with ZODB5

See also https://github.com/zopefoundation/ZEO/pull/63
     and https://lab.nexedi.com/nexedi/erp5/merge_requests/1095

No error in testCMFActivity and testConflictResolution.
For the only error in testInvalidationBug, see comment.

But this commit is not enough for ZODB5. The only known issue so far
is the use of newer pickle protocol, which breaks export of ZODB data
and requires non-trivial changes in our XMLExportImport/ppml code.
So for the moment, many failures in testBusinessTempate.
---
 product/ERP5/tests/testInvalidationBug.py   |  3 ++
 product/ERP5Type/patches/DemoStorage.py     |  3 +-
 product/ERP5Type/patches/XMLExportImport.py |  4 +--
 product/ERP5Type/patches/ZODBConnection.py  | 35 +++++++++------------
 product/ERP5Type/tests/custom_zodb.py       |  5 ++-
 5 files changed, 24 insertions(+), 26 deletions(-)

diff --git a/product/ERP5/tests/testInvalidationBug.py b/product/ERP5/tests/testInvalidationBug.py
index 5251983929..af721dd02d 100644
--- a/product/ERP5/tests/testInvalidationBug.py
+++ b/product/ERP5/tests/testInvalidationBug.py
@@ -90,6 +90,9 @@ class TestInvalidationBug(ERP5TypeTestCase):
     self.assertEqual(result_list[-2], None)  # ZODB
     self.assertEqual(result_list[-1], [1,1]) # activity tables last
 
+  # TODO: - skip this test for ZEO>=5 because it's covered upstream
+  #         (and later remove it)
+  #       - in slapos.git, enable server_sync in zope.conf
   def testLateInvalidationFromZEO(self):
     ### Check unit test is run properly
     from ZEO.ClientStorage import ClientStorage
diff --git a/product/ERP5Type/patches/DemoStorage.py b/product/ERP5Type/patches/DemoStorage.py
index 87ce80303f..0803eab458 100644
--- a/product/ERP5Type/patches/DemoStorage.py
+++ b/product/ERP5Type/patches/DemoStorage.py
@@ -13,7 +13,7 @@
 ##############################################################################
 
 from ZODB import DemoStorage as _DemoStorage
-from ZODB.ConflictResolution import ConflictResolvingStorage, ResolvedSerial
+from ZODB.ConflictResolution import ConflictResolvingStorage
 from ZODB.POSException import ConflictError
 
 class DemoStorage(_DemoStorage.DemoStorage, ConflictResolvingStorage):
@@ -33,4 +33,5 @@ class DemoStorage(_DemoStorage.DemoStorage, ConflictResolvingStorage):
 
 if not issubclass(_DemoStorage.DemoStorage, ConflictResolvingStorage):
     # BBB: ZODB < 4.3
+    from ZODB.ConflictResolution import ResolvedSerial
     _DemoStorage.DemoStorage = DemoStorage
diff --git a/product/ERP5Type/patches/XMLExportImport.py b/product/ERP5Type/patches/XMLExportImport.py
index fd8bdbcf59..5f8f689901 100644
--- a/product/ERP5Type/patches/XMLExportImport.py
+++ b/product/ERP5Type/patches/XMLExportImport.py
@@ -107,9 +107,7 @@ def exportXML(jar, oid, file=None):
     def getReorderedPickle(oid):
         p = pickle_dict[oid]
         if p is None:
-            # Versions are ignored, but some 'load()' implementations require them
-            # FIXME: remove "''" when TmpStore.load() on ZODB stops asking for it.
-            p = load(oid, '')[0]
+            p = load(oid)[0]
             p = reorderPickle(jar, p)[1]
             if len(p) < max_cache[0]:
                 max_cache[0] -= len(p)
diff --git a/product/ERP5Type/patches/ZODBConnection.py b/product/ERP5Type/patches/ZODBConnection.py
index 7626943056..eda7aa9d95 100644
--- a/product/ERP5Type/patches/ZODBConnection.py
+++ b/product/ERP5Type/patches/ZODBConnection.py
@@ -11,36 +11,29 @@
 #
 ##############################################################################
 
-# override ZODB.Connection.newTransaction() to do a synchronous call before
-# flushing all invalidations, this will serve as a "network barrier" that
-# will force Connection to wait for all invalidations sent from other parallel
-# transactions so that, for instance, activity processing can see a recent
-# enough state of the ZODB.
-
 import time
 from Products.ERP5Type.Timeout import TimeoutReachedError, getDeadline
 from ZODB.Connection import Connection
 
 FORCE_STORAGE_SYNC_ON_CONNECTION_OPENING = False
 
-if 1: # keep indentation. Also good for quick disabling.
+if 1: # for quick disabling.
 
-    def ping(self):
-        # Use a synchronous call to make sure we have received all invalidation
-        # methods that could be stuck in the wire so MVCC behaves correctly.
-        # XXX Use a proper ping method exported by ClientStorage instead of
-        # this hack
-        ping = getattr(getattr(self._storage, '_server', None),
-                       'getAuthProtocol',
-                       lambda: None)
-        ping()
+    if hasattr(Connection, '_storage_sync'): # ZODB<5
+        # BBB: For ZEO<5, use a synchronous call to make sure we have received
+        #      all invalidation methods that could be stuck in the wire so MVCC
+        #      behaves correctly. This can be seen as a "network barrier",
+        #      so that, for instance, activity processing can see a recent
+        #      enough state of the ZODB.
+        #      ZEO5 has an option and NEO does it by default.
 
-    def newTransaction(self, *ignored):
-        self.ping()
-        self._storage_sync()
+        def newTransaction(self, *ignored):
+            zeo = getattr(self._storage, '_server', None)
+            if zeo is not None:
+                zeo.getAuthProtocol()
+            self._storage_sync()
 
-    Connection.ping = ping
-    Connection.newTransaction = newTransaction
+        Connection.newTransaction = newTransaction
 
     if FORCE_STORAGE_SYNC_ON_CONNECTION_OPENING:
 
diff --git a/product/ERP5Type/tests/custom_zodb.py b/product/ERP5Type/tests/custom_zodb.py
index 0a2bed44f5..15f2ebb339 100644
--- a/product/ERP5Type/tests/custom_zodb.py
+++ b/product/ERP5Type/tests/custom_zodb.py
@@ -168,7 +168,10 @@ else:
   else:
     forkNodes()
     from ZEO.ClientStorage import ClientStorage
-    Storage = ClientStorage(zeo_client)
+    try:
+        Storage = ClientStorage(zeo_client, server_sync=True)
+    except TypeError: # BBB: ZEO<5
+        Storage = ClientStorage(zeo_client)
 
 if node_pid_list is not None:
   _print("Instance at %r loaded ... " % instance_home)
-- 
2.30.9