Skip to content

Commit

Permalink
Added a ClientStorage server-sync configuration option and
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Jim Fulton committed Aug 4, 2016
1 parent 9613f09 commit deaa913
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 4 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
@@ -1,6 +1,11 @@
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)
Expand Down
20 changes: 20 additions & 0 deletions README.rst
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion src/ZEO/ClientStorage.py
Expand Up @@ -95,8 +95,10 @@ def __init__(self, addr, storage='1', cache_size=20 * MB,
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,
):
Expand Down Expand Up @@ -181,6 +183,8 @@ def __init__(self, addr, storage='1', cache_size=20 * MB,
"""

assert not username or password or realm

if isinstance(addr, int):
addr = ('127.0.0.1', addr)

Expand Down Expand Up @@ -268,6 +272,8 @@ def __init__(self, addr, storage='1', cache_size=20 * MB,

self._commit_lock = threading.Lock()

self.server_sync = server_sync

if wait:
try:
self._wait()
Expand Down Expand Up @@ -377,6 +383,14 @@ def notify_connected(self, conn, info):
'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):
Expand Down
6 changes: 4 additions & 2 deletions src/ZEO/StorageServer.py
Expand Up @@ -73,7 +73,7 @@ class StorageServerError(StorageError):
'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."""
Expand Down Expand Up @@ -614,6 +614,9 @@ def set_client_label(self, label):
def ruok(self):
return self.server.ruok()

def ping(self):
pass

class StorageServerDB:
"""Adapter from StorageServerDB to ZODB.interfaces.IStorageWrapper
Expand Down Expand Up @@ -949,7 +952,6 @@ def ruok(self):
return dict((storage_id, self.server_status(storage_id))
for storage_id in self.storages)


class StubTimeoutThread:

def begin(self, client):
Expand Down
9 changes: 9 additions & 0 deletions src/ZEO/component.xml
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/ZEO/tests/ConnectionTests.py
Expand Up @@ -769,7 +769,7 @@ def checkReconnectUpgrade(self):

# 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)
Expand Down
2 changes: 2 additions & 0 deletions src/ZEO/tests/testConfig.py
Expand Up @@ -62,6 +62,7 @@ def _client_assertions(
blob_cache_size_check=10,
read_only=False,
read_only_fallback=False,
server_sync=False,
wait_timeout=30,
client_label=None,
storage='1',
Expand Down Expand Up @@ -106,6 +107,7 @@ def test_client_variations(self):
blob_cache_size=424242,
read_only=True,
read_only_fallback=True,
server_sync=True,
wait_timeout=33,
client_label='test_client',
name='Test'
Expand Down
1 change: 1 addition & 0 deletions src/ZEO/zconfig.py
Expand Up @@ -85,5 +85,6 @@ def open(self):
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)

0 comments on commit deaa913

Please sign in to comment.