Skip to content

Commit b4472cd

Browse files
committed
api: extend connect with fetch_schema param
Added support of the fetch_schema parameter, which allows to ignore schema changes on the server. Closes #219
1 parent d0126c8 commit b4472cd

11 files changed

+355
-96
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,5 @@ test/data/*.key
5353
!test/data/localhost.enc.key
5454
test/data/*.pem
5555
test/data/*.srl
56+
57+
.rocks

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313
to decrypt private SSL key file (#224).
1414
- Support specifying authentication method with `auth_type`
1515
and Tarantool EE `pap-sha256` authentication method (#269).
16+
- Support of the fetch_schema parameter for connection (#219).
1617

1718
### Changed
1819

docs/source/quick-start.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ Through the :class:`~tarantool.Connection` object, you can access
359359
360360
>>> import tarantool
361361
>>> from tarantool.error import CrudModuleError, CrudModuleManyError, DatabaseError
362-
>>> conn = tarantool.Connection(host='localhost',port=3301)
362+
>>> conn = tarantool.Connection(host='localhost',port=3301,fetch_schema=False)
363363
364364
>>> conn.crud_
365365
conn.crud_count( conn.crud_insert( conn.crud_insert_object_many(

tarantool/connection.py

+59-10
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,8 @@ def __init__(self, host, port,
579579
ssl_password_file=DEFAULT_SSL_PASSWORD_FILE,
580580
packer_factory=default_packer_factory,
581581
unpacker_factory=default_unpacker_factory,
582-
auth_type=None):
582+
auth_type=None,
583+
fetch_schema=True):
583584
"""
584585
:param host: Server hostname or IP address. Use ``None`` for
585586
Unix sockets.
@@ -736,6 +737,18 @@ def __init__(self, host, port,
736737
``"chap-sha1"``.
737738
:type auth_type: :obj:`None` or :obj:`str`, optional
738739
740+
:param bool fetch_schema: If ``False``, allows to ignore schema
741+
changes on the server, schema updates are not automatically
742+
loaded. As a result, these methods become unavailable:
743+
:meth:`~tarantool.Connection.replace`,
744+
:meth:`~tarantool.Connection.insert`,
745+
:meth:`~tarantool.Connection.delete`,
746+
:meth:`~tarantool.Connection.upsert`,
747+
:meth:`~tarantool.Connection.update`,
748+
:meth:`~tarantool.Connection.select`,
749+
:meth:`~tarantool.Connection.space`.
750+
:type fetch_schema: :obj:`bool`, optional
751+
739752
:raise: :exc:`~tarantool.error.ConfigurationError`,
740753
:meth:`~tarantool.Connection.connect` exceptions
741754
@@ -766,6 +779,7 @@ def __init__(self, host, port,
766779
self.socket_timeout = socket_timeout
767780
self.reconnect_delay = reconnect_delay
768781
self.reconnect_max_attempts = reconnect_max_attempts
782+
self.fetch_schema = fetch_schema
769783
self.schema = Schema(self)
770784
self.schema_version = 1
771785
self._socket = None
@@ -1023,7 +1037,9 @@ def connect(self):
10231037
if self.transport == SSL_TRANSPORT:
10241038
self.wrap_socket_ssl()
10251039
self.handshake()
1026-
self.load_schema()
1040+
if self.fetch_schema:
1041+
self.load_schema()
1042+
self._check_features()
10271043
except SslError as e:
10281044
raise e
10291045
except Exception as e:
@@ -1118,7 +1134,8 @@ def _send_request_wo_reconnect(self, request, on_push=None, on_push_ctx=None):
11181134
response = request.response_class(self, self._read_response())
11191135
break
11201136
except SchemaReloadException as e:
1121-
self.update_schema(e.schema_version)
1137+
if self.fetch_schema:
1138+
self.update_schema(e.schema_version)
11221139
continue
11231140

11241141
while response._code == IPROTO_CHUNK:
@@ -1269,6 +1286,18 @@ def flush_schema(self):
12691286
self.schema.flush()
12701287
self.load_schema()
12711288

1289+
def _fetch_schema_support_check(self):
1290+
"""
1291+
Checks the fetch_schema opt of the connection is enabled.
1292+
If the opt is disabled, an exception will be thrown
1293+
about unsupporting the method with fetch_schema=False.
1294+
1295+
:raise: :exc:`~tarantool.error.NotSupportedError`
1296+
"""
1297+
if not self.fetch_schema:
1298+
raise NotSupportedError('This method is not available in ' +
1299+
'connection opened with fetch_schema=False')
1300+
12721301
def call(self, func_name, *args, on_push=None, on_push_ctx=None):
12731302
"""
12741303
Execute a CALL request: call a stored Lua function.
@@ -1366,11 +1395,14 @@ def replace(self, space_name, values, on_push=None, on_push_ctx=None):
13661395
:exc:`~tarantool.error.DatabaseError`,
13671396
:exc:`~tarantool.error.SchemaError`,
13681397
:exc:`~tarantool.error.NetworkError`,
1369-
:exc:`~tarantool.error.SslError`
1398+
:exc:`~tarantool.error.SslError`,
1399+
:exc:`~tarantool.error.NotSupportedError`
13701400
13711401
.. _replace: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/replace/
13721402
"""
13731403

1404+
self._fetch_schema_support_check()
1405+
13741406
if isinstance(space_name, str):
13751407
space_name = self.schema.get_space(space_name).sid
13761408
if on_push is not None and not callable(on_push):
@@ -1411,7 +1443,7 @@ def authenticate(self, user, password):
14111443
password=self.password,
14121444
auth_type=self._get_auth_type())
14131445
auth_response = self._send_request_wo_reconnect(request)
1414-
if auth_response.return_code == 0:
1446+
if auth_response.return_code == 0 and self.fetch_schema:
14151447
self.flush_schema()
14161448
return auth_response
14171449

@@ -1584,11 +1616,14 @@ def insert(self, space_name, values, on_push=None, on_push_ctx=None):
15841616
:exc:`~tarantool.error.DatabaseError`,
15851617
:exc:`~tarantool.error.SchemaError`,
15861618
:exc:`~tarantool.error.NetworkError`,
1587-
:exc:`~tarantool.error.SslError`
1619+
:exc:`~tarantool.error.SslError`,
1620+
:exc:`~tarantool.error.NotSupportedError`
15881621
15891622
.. _insert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/insert/
15901623
"""
15911624

1625+
self._fetch_schema_support_check()
1626+
15921627
if isinstance(space_name, str):
15931628
space_name = self.schema.get_space(space_name).sid
15941629
if on_push is not None and not callable(on_push):
@@ -1623,11 +1658,14 @@ def delete(self, space_name, key, *, index=0, on_push=None, on_push_ctx=None):
16231658
:exc:`~tarantool.error.DatabaseError`,
16241659
:exc:`~tarantool.error.SchemaError`,
16251660
:exc:`~tarantool.error.NetworkError`,
1626-
:exc:`~tarantool.error.SslError`
1661+
:exc:`~tarantool.error.SslError`,
1662+
:exc:`~tarantool.error.NotSupportedError`
16271663
16281664
.. _delete: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/delete/
16291665
"""
16301666

1667+
self._fetch_schema_support_check()
1668+
16311669
key = wrap_key(key)
16321670
if isinstance(space_name, str):
16331671
space_name = self.schema.get_space(space_name).sid
@@ -1682,11 +1720,14 @@ def upsert(self, space_name, tuple_value, op_list, *, index=0, on_push=None, on_
16821720
:exc:`~tarantool.error.DatabaseError`,
16831721
:exc:`~tarantool.error.SchemaError`,
16841722
:exc:`~tarantool.error.NetworkError`,
1685-
:exc:`~tarantool.error.SslError`
1723+
:exc:`~tarantool.error.SslError`,
1724+
:exc:`~tarantool.error.NotSupportedError`
16861725
16871726
.. _upsert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/upsert/
16881727
"""
16891728

1729+
self._fetch_schema_support_check()
1730+
16901731
if isinstance(space_name, str):
16911732
space_name = self.schema.get_space(space_name).sid
16921733
if isinstance(index, str):
@@ -1770,11 +1811,14 @@ def update(self, space_name, key, op_list, *, index=0, on_push=None, on_push_ctx
17701811
:exc:`~tarantool.error.DatabaseError`,
17711812
:exc:`~tarantool.error.SchemaError`,
17721813
:exc:`~tarantool.error.NetworkError`,
1773-
:exc:`~tarantool.error.SslError`
1814+
:exc:`~tarantool.error.SslError`,
1815+
:exc:`~tarantool.error.NotSupportedError`
17741816
17751817
.. _update: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/update/
17761818
"""
17771819

1820+
self._fetch_schema_support_check()
1821+
17781822
key = wrap_key(key)
17791823
if isinstance(space_name, str):
17801824
space_name = self.schema.get_space(space_name).sid
@@ -1956,11 +2000,14 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i
19562000
:exc:`~tarantool.error.DatabaseError`,
19572001
:exc:`~tarantool.error.SchemaError`,
19582002
:exc:`~tarantool.error.NetworkError`,
1959-
:exc:`~tarantool.error.SslError`
2003+
:exc:`~tarantool.error.SslError`,
2004+
:exc:`~tarantool.error.NotSupportedError`
19602005
19612006
.. _select: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/select/
19622007
"""
19632008

2009+
self._fetch_schema_support_check()
2010+
19642011
if iterator is None:
19652012
iterator = ITERATOR_EQ
19662013
if key is None or (isinstance(key, (list, tuple)) and
@@ -1996,6 +2043,8 @@ def space(self, space_name):
19962043
:raise: :exc:`~tarantool.error.SchemaError`
19972044
"""
19982045

2046+
self._fetch_schema_support_check()
2047+
19992048
return Space(self, space_name)
20002049

20012050
def generate_sync(self):

tarantool/connection_pool.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ def __init__(self,
378378
call_16=False,
379379
connection_timeout=CONNECTION_TIMEOUT,
380380
strategy_class=RoundRobinStrategy,
381-
refresh_delay=POOL_REFRESH_DELAY):
381+
refresh_delay=POOL_REFRESH_DELAY,
382+
fetch_schema=True):
382383
"""
383384
:param addrs: List of dictionaries describing server addresses:
384385
@@ -452,6 +453,9 @@ def __init__(self,
452453
`box.info.ro`_ status background refreshes, in seconds.
453454
:type connection_timeout: :obj:`float`, optional
454455
456+
:param fetch_schema: Refer to
457+
:paramref:`~tarantool.Connection.params.fetch_schema`.
458+
455459
:raise: :exc:`~tarantool.error.ConfigurationError`,
456460
:class:`~tarantool.Connection` exceptions
457461
@@ -500,7 +504,8 @@ def __init__(self,
500504
ssl_ciphers=addr['ssl_ciphers'],
501505
ssl_password=addr['ssl_password'],
502506
ssl_password_file=addr['ssl_password_file'],
503-
auth_type=addr['auth_type'])
507+
auth_type=addr['auth_type'],
508+
fetch_schema=fetch_schema)
504509
)
505510

506511
if connect_now:

tarantool/mesh_connection.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,8 @@ def __init__(self, host=None, port=None,
283283
addrs=None,
284284
strategy_class=RoundRobinStrategy,
285285
cluster_discovery_function=None,
286-
cluster_discovery_delay=CLUSTER_DISCOVERY_DELAY):
286+
cluster_discovery_delay=CLUSTER_DISCOVERY_DELAY,
287+
fetch_schema=True):
287288
"""
288289
:param host: Refer to
289290
:paramref:`~tarantool.Connection.params.host`.
@@ -425,6 +426,9 @@ def __init__(self, host=None, port=None,
425426
list refresh.
426427
:type cluster_discovery_delay: :obj:`float`, optional
427428
429+
:param fetch_schema: Refer to
430+
:paramref:`~tarantool.Connection.params.fetch_schema`.
431+
428432
:raises: :exc:`~tarantool.error.ConfigurationError`,
429433
:class:`~tarantool.Connection` exceptions,
430434
:class:`~tarantool.MeshConnection.connect` exceptions
@@ -489,7 +493,8 @@ def __init__(self, host=None, port=None,
489493
ssl_ciphers=addr['ssl_ciphers'],
490494
ssl_password=addr['ssl_password'],
491495
ssl_password_file=addr['ssl_password_file'],
492-
auth_type=addr['auth_type'])
496+
auth_type=addr['auth_type'],
497+
fetch_schema=fetch_schema)
493498

494499
def connect(self):
495500
"""

tarantool/request.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,13 @@ def header(self, length):
188188
"""
189189

190190
self._sync = self.conn.generate_sync()
191-
header = self._dumps({IPROTO_REQUEST_TYPE: self.request_type,
192-
IPROTO_SYNC: self._sync,
193-
IPROTO_SCHEMA_ID: self.conn.schema_version})
191+
header_fields = {
192+
IPROTO_REQUEST_TYPE: self.request_type,
193+
IPROTO_SYNC: self._sync,
194+
}
195+
if self.conn.fetch_schema:
196+
header_fields[IPROTO_SCHEMA_ID] = self.conn.schema_version
197+
header = self._dumps(header_fields)
194198

195199
return self._dumps(length + len(header)) + header
196200

0 commit comments

Comments
 (0)