Skip to content

Commit ca0a514

Browse files
GRISHNOVDifferentialOrange
authored andcommitted
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 2400297 commit ca0a514

File tree

9 files changed

+309
-30
lines changed

9 files changed

+309
-30
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
@@ -5,6 +5,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## Unreleased
8+
- Support `fetch_schema` parameter for a connection (#219).
89

910
### Added
1011

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

+67-12
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``, schema is not loaded on connect
741+
and schema updates are not automatically loaded.
742+
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,8 +779,9 @@ 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
769-
self.schema = Schema(self)
770-
self.schema_version = 1
782+
self.fetch_schema = fetch_schema
783+
self.schema = None
784+
self.schema_version = 0
771785
self._socket = None
772786
self.connected = False
773787
self.error = True
@@ -1023,7 +1037,11 @@ 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.schema = Schema(self)
1042+
self.load_schema()
1043+
else:
1044+
self.schema = None
10271045
except SslError as e:
10281046
raise e
10291047
except Exception as e:
@@ -1118,7 +1136,8 @@ def _send_request_wo_reconnect(self, request, on_push=None, on_push_ctx=None):
11181136
response = request.response_class(self, self._read_response())
11191137
break
11201138
except SchemaReloadException as e:
1121-
self.update_schema(e.schema_version)
1139+
if self.schema is not None:
1140+
self.update_schema(e.schema_version)
11221141
continue
11231142

11241143
while response._code == IPROTO_CHUNK:
@@ -1255,6 +1274,9 @@ def update_schema(self, schema_version):
12551274
:meta private:
12561275
"""
12571276

1277+
if self.schema is None:
1278+
self.schema = Schema(self)
1279+
12581280
self.schema_version = schema_version
12591281
self.flush_schema()
12601282

@@ -1269,6 +1291,19 @@ def flush_schema(self):
12691291
self.schema.flush()
12701292
self.load_schema()
12711293

1294+
def _schemaful_connection_check(self):
1295+
"""
1296+
Checks whether the connection is schemaful.
1297+
If the connection is schemaless, an exception will be thrown
1298+
about unsupporting the method in connection opened
1299+
with fetch_schema=False.
1300+
1301+
:raise: :exc:`~tarantool.error.NotSupportedError`
1302+
"""
1303+
if self.schema is None:
1304+
raise NotSupportedError('This method is not available in ' +
1305+
'connection opened with fetch_schema=False')
1306+
12721307
def call(self, func_name, *args, on_push=None, on_push_ctx=None):
12731308
"""
12741309
Execute a CALL request: call a stored Lua function.
@@ -1366,11 +1401,14 @@ def replace(self, space_name, values, on_push=None, on_push_ctx=None):
13661401
:exc:`~tarantool.error.DatabaseError`,
13671402
:exc:`~tarantool.error.SchemaError`,
13681403
:exc:`~tarantool.error.NetworkError`,
1369-
:exc:`~tarantool.error.SslError`
1404+
:exc:`~tarantool.error.SslError`,
1405+
:exc:`~tarantool.error.NotSupportedError`
13701406
13711407
.. _replace: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/replace/
13721408
"""
13731409

1410+
self._schemaful_connection_check()
1411+
13741412
if isinstance(space_name, str):
13751413
space_name = self.schema.get_space(space_name).sid
13761414
if on_push is not None and not callable(on_push):
@@ -1411,7 +1449,7 @@ def authenticate(self, user, password):
14111449
password=self.password,
14121450
auth_type=self._get_auth_type())
14131451
auth_response = self._send_request_wo_reconnect(request)
1414-
if auth_response.return_code == 0:
1452+
if auth_response.return_code == 0 and self.schema is not None:
14151453
self.flush_schema()
14161454
return auth_response
14171455

@@ -1584,11 +1622,14 @@ def insert(self, space_name, values, on_push=None, on_push_ctx=None):
15841622
:exc:`~tarantool.error.DatabaseError`,
15851623
:exc:`~tarantool.error.SchemaError`,
15861624
:exc:`~tarantool.error.NetworkError`,
1587-
:exc:`~tarantool.error.SslError`
1625+
:exc:`~tarantool.error.SslError`,
1626+
:exc:`~tarantool.error.NotSupportedError`
15881627
15891628
.. _insert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/insert/
15901629
"""
15911630

1631+
self._schemaful_connection_check()
1632+
15921633
if isinstance(space_name, str):
15931634
space_name = self.schema.get_space(space_name).sid
15941635
if on_push is not None and not callable(on_push):
@@ -1623,11 +1664,14 @@ def delete(self, space_name, key, *, index=0, on_push=None, on_push_ctx=None):
16231664
:exc:`~tarantool.error.DatabaseError`,
16241665
:exc:`~tarantool.error.SchemaError`,
16251666
:exc:`~tarantool.error.NetworkError`,
1626-
:exc:`~tarantool.error.SslError`
1667+
:exc:`~tarantool.error.SslError`,
1668+
:exc:`~tarantool.error.NotSupportedError`
16271669
16281670
.. _delete: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/delete/
16291671
"""
16301672

1673+
self._schemaful_connection_check()
1674+
16311675
key = wrap_key(key)
16321676
if isinstance(space_name, str):
16331677
space_name = self.schema.get_space(space_name).sid
@@ -1682,11 +1726,14 @@ def upsert(self, space_name, tuple_value, op_list, *, index=0, on_push=None, on_
16821726
:exc:`~tarantool.error.DatabaseError`,
16831727
:exc:`~tarantool.error.SchemaError`,
16841728
:exc:`~tarantool.error.NetworkError`,
1685-
:exc:`~tarantool.error.SslError`
1729+
:exc:`~tarantool.error.SslError`,
1730+
:exc:`~tarantool.error.NotSupportedError`
16861731
16871732
.. _upsert: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/upsert/
16881733
"""
16891734

1735+
self._schemaful_connection_check()
1736+
16901737
if isinstance(space_name, str):
16911738
space_name = self.schema.get_space(space_name).sid
16921739
if isinstance(index, str):
@@ -1770,11 +1817,14 @@ def update(self, space_name, key, op_list, *, index=0, on_push=None, on_push_ctx
17701817
:exc:`~tarantool.error.DatabaseError`,
17711818
:exc:`~tarantool.error.SchemaError`,
17721819
:exc:`~tarantool.error.NetworkError`,
1773-
:exc:`~tarantool.error.SslError`
1820+
:exc:`~tarantool.error.SslError`,
1821+
:exc:`~tarantool.error.NotSupportedError`
17741822
17751823
.. _update: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/update/
17761824
"""
17771825

1826+
self._schemaful_connection_check()
1827+
17781828
key = wrap_key(key)
17791829
if isinstance(space_name, str):
17801830
space_name = self.schema.get_space(space_name).sid
@@ -1956,11 +2006,14 @@ def select(self, space_name, key=None, *, offset=0, limit=0xffffffff, index=0, i
19562006
:exc:`~tarantool.error.DatabaseError`,
19572007
:exc:`~tarantool.error.SchemaError`,
19582008
:exc:`~tarantool.error.NetworkError`,
1959-
:exc:`~tarantool.error.SslError`
2009+
:exc:`~tarantool.error.SslError`,
2010+
:exc:`~tarantool.error.NotSupportedError`
19602011
19612012
.. _select: https://www.tarantool.io/en/doc/latest/reference/reference_lua/box_space/select/
19622013
"""
19632014

2015+
self._schemaful_connection_check()
2016+
19642017
if iterator is None:
19652018
iterator = ITERATOR_EQ
19662019
if key is None or (isinstance(key, (list, tuple)) and
@@ -1996,6 +2049,8 @@ def space(self, space_name):
19962049
:raise: :exc:`~tarantool.error.SchemaError`
19972050
"""
19982051

2052+
self._schemaful_connection_check()
2053+
19992054
return Space(self, space_name)
20002055

20012056
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.schema is not None:
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

test/suites/test_crud.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,12 @@ def setUp(self):
3333
time.sleep(1)
3434
# Open connections to instance.
3535
self.conn = tarantool.Connection(host=self.host, port=self.port,
36-
user='guest', password='')
36+
user='guest', password='', fetch_schema=False)
3737
self.conn_mesh = tarantool.MeshConnection(host=self.host, port=self.port,
38-
user='guest', password='')
38+
user='guest', password='', fetch_schema=False)
3939
self.conn_pool = tarantool.ConnectionPool([{'host':self.host, 'port':self.port}],
40-
user='guest', password='')
40+
user='guest', password='',
41+
fetch_schema=False)
4142
# Time for vshard group configuration.
4243
time.sleep(1)
4344
if self.conn.eval('return ROCKS_IMPORT_FAIL').data[0] == True:

0 commit comments

Comments
 (0)