Commit deaa913c authored by Jim Fulton's avatar Jim Fulton

Added a ClientStorage server-sync configuration option and

server_sync constructor argument to force a server round trip at
the beginning of transactions to wait for any outstanding
invalidations at the start of the transaction to be delivered.
parent 9613f09b
Changelog
=========
- Added a ``ClientStorage`` ``server-sync`` configuration option and
``server_sync`` constructor argument to force a server round trip at
the beginning of transactions to wait for any outstanding
invalidations at the start of the transaction to be delivered.
- Fixed bugs in using the ZEO 5 client with ZEO 4 servers.
5.0.0a2 (2016-07-30)
......
......@@ -456,6 +456,23 @@ read_only_fallback
If ``read_only_fallback`` is set, then ``read_only`` is ignored.
server_sync
Flag, false by default, indicating whether the ``sync`` method
should make a server request. The ``sync`` method is called at the
start of explcitly begin transactions. Making a server requests assures
that any invalidations outstanding at the beginning of a
transaction are processed.
Setting this to True is important when application activity is
spread over multiple ZEO clients. The classic example of this is
when a web browser makes a request to an application server (ZEO
client) that makes a change and then makes a request to another
application server that depends on the change.
Setting this to True makes transactions a little slower because of
the added server round trip. For transactions that don't otherwise
need to access the storage server, the impact can be significant.
wait_timeout
How long to wait for an initial connection, defaulting to 30
seconds. If an initial connection can't be made within this time
......@@ -567,6 +584,9 @@ read-only-fallback
If ``read_only_fallback`` is set, then ``read_only`` is ignored.
server-sync
Sets thr ``server_sync`` option described above.
wait_timeout
How long to wait for an initial connection, defaulting to 30
seconds. If an initial connection can't be made within this time
......
......@@ -95,8 +95,10 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
min_disconnect_poll=1, max_disconnect_poll=None,
wait=True,
drop_cache_rather_verify=True,
username=None, password=None, realm=None,
credentials=None,
server_sync=False,
# The ZODB-define ZConfig support may ball these:
username=None, password=None, realm=None,
# For tests:
_client_factory=ZEO.asyncio.client.ClientThread,
):
......@@ -181,6 +183,8 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
"""
assert not username or password or realm
if isinstance(addr, int):
addr = ('127.0.0.1', addr)
......@@ -268,6 +272,8 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
self._commit_lock = threading.Lock()
self.server_sync = server_sync
if wait:
try:
self._wait()
......@@ -377,6 +383,14 @@ class ClientStorage(ZODB.ConflictResolution.ConflictResolvingStorage):
'interfaces', ()):
zope.interface.alsoProvides(self, iface)
if self.protocol_version >= b'Z5':
self.ping = lambda : self._call('ping')
else:
self.ping = lambda : self._call('lastTransaction')
if self.server_sync:
self.sync = self.ping
def set_server_addr(self, addr):
# Normalize server address and convert to string
if isinstance(addr, str):
......
......@@ -73,7 +73,7 @@ registered_methods = set(( 'get_info', 'lastTransaction',
'history', 'record_iternext', 'sendBlob', 'getTid', 'loadSerial',
'new_oid', 'undoa', 'undoLog', 'undoInfo', 'iterator_start',
'iterator_next', 'iterator_record_start', 'iterator_record_next',
'iterator_gc', 'server_status', 'set_client_label'))
'iterator_gc', 'server_status', 'set_client_label', 'ping'))
class ZEOStorage:
"""Proxy to underlying storage for a single remote client."""
......@@ -614,6 +614,9 @@ class ZEOStorage:
def ruok(self):
return self.server.ruok()
def ping(self):
pass
class StorageServerDB:
"""Adapter from StorageServerDB to ZODB.interfaces.IStorageWrapper
......@@ -949,7 +952,6 @@ class StorageServer:
return dict((storage_id, self.server_status(storage_id))
for storage_id in self.storages)
class StubTimeoutThread:
def begin(self, client):
......
......@@ -120,6 +120,15 @@
</description>
</key>
<key name="server-sync" datatype="boolean" default="off">
<description>
A flag indicating whether calls to sync() should make a server
request, thus causing the storage to wait for any outstanding
invalidations. The sync method is called when transactions are
explicitly begun.
</description>
</key>
<key name="wait-timeout" datatype="integer" default="30">
<description>
How long to wait for an initial connection, defaulting to 30
......
......@@ -769,7 +769,7 @@ class ReconnectionTests(CommonSetupTearDown):
# Accesses should fail now
with short_timeout(self):
self.assertRaises(ClientDisconnected, self._storage.history, ZERO)
self.assertRaises(ClientDisconnected, self._storage.ping)
# Restart the server, this time read-write
self.startServer(create=0, keep=0)
......
......@@ -62,6 +62,7 @@ class ZEOConfigTestBase(setupstack.TestCase):
blob_cache_size_check=10,
read_only=False,
read_only_fallback=False,
server_sync=False,
wait_timeout=30,
client_label=None,
storage='1',
......@@ -106,6 +107,7 @@ class ZEOConfigTest(ZEOConfigTestBase):
blob_cache_size=424242,
read_only=True,
read_only_fallback=True,
server_sync=True,
wait_timeout=33,
client_label='test_client',
name='Test'
......
......@@ -85,5 +85,6 @@ class ClientStorageConfig:
name=config.name,
read_only=config.read_only,
read_only_fallback=config.read_only_fallback,
server_sync = config.server_sync,
wait_timeout=config.wait_timeout,
**options)
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