e6data-python-connector 2.1.21__tar.gz → 2.1.21.dev0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {e6data_python_connector-2.1.21/e6data_python_connector.egg-info → e6data_python_connector-2.1.21.dev0}/PKG-INFO +1 -1
- e6data_python_connector-2.1.21.dev0/e6data_python_connector/cluster_manager.py +117 -0
- e6data_python_connector-2.1.21.dev0/e6data_python_connector/cluster_server/__init__.py +0 -0
- e6data_python_connector-2.1.21.dev0/e6data_python_connector/cluster_server/cluster_pb2.py +38 -0
- e6data_python_connector-2.1.21.dev0/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +132 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/e6data_grpc.py +35 -1
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0/e6data_python_connector.egg-info}/PKG-INFO +1 -1
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector.egg-info/SOURCES.txt +4 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/setup.py +1 -1
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/LICENSE +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/MANIFEST.in +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/README.md +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/__init__.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/common.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/constants.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/datainputstream.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/date_time_utils.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/dialect.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/exceptions.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/QueryEngineService.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/__init__.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/constants.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/server/ttypes.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector/typeId.py +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector.egg-info/entry_points.txt +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector.egg-info/requires.txt +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/e6data_python_connector.egg-info/top_level.txt +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/pyproject.toml +0 -0
- {e6data_python_connector-2.1.21 → e6data_python_connector-2.1.21.dev0}/setup.cfg +0 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
import time
|
|
3
|
+
import e6data_python_connector.cluster_server.cluster_pb2 as cluster_pb2
|
|
4
|
+
import e6data_python_connector.cluster_server.cluster_pb2_grpc as cluster_pb2_grpc
|
|
5
|
+
import grpc
|
|
6
|
+
from grpc._channel import _InactiveRpcError
|
|
7
|
+
import multiprocessing
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class _StatusLock:
|
|
11
|
+
_LOCK_TIMEOUT = 500
|
|
12
|
+
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self._status_thread_lock = threading.Lock()
|
|
15
|
+
self._status_multiprocessing_lock = multiprocessing.Semaphore()
|
|
16
|
+
self._is_active = False
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def is_active(self) -> bool:
|
|
20
|
+
return self._is_active
|
|
21
|
+
|
|
22
|
+
def set_active(self):
|
|
23
|
+
self._is_active = True
|
|
24
|
+
|
|
25
|
+
def __enter__(self):
|
|
26
|
+
self._status_thread_lock.acquire(timeout=self._LOCK_TIMEOUT)
|
|
27
|
+
self._status_multiprocessing_lock.acquire(timeout=self._LOCK_TIMEOUT)
|
|
28
|
+
print('Locked threads and processes.')
|
|
29
|
+
return self
|
|
30
|
+
|
|
31
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
32
|
+
self._status_thread_lock.release()
|
|
33
|
+
self._status_multiprocessing_lock.release()
|
|
34
|
+
print('Released threads and processes.')
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
status_lock = _StatusLock()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ClusterManager:
|
|
41
|
+
def __init__(self, host: str, port: int, user: str, password: str, secure_channel: bool = False, timeout=60 * 3):
|
|
42
|
+
self._host = host
|
|
43
|
+
self._port = port
|
|
44
|
+
self._user = user
|
|
45
|
+
self._password = password
|
|
46
|
+
self._timeout = time.time() + timeout
|
|
47
|
+
self._secure_channel = secure_channel
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def _get_connection(self):
|
|
51
|
+
if self._secure_channel:
|
|
52
|
+
self._channel = grpc.secure_channel(
|
|
53
|
+
target='{}:{}'.format(self._host, self._port),
|
|
54
|
+
credentials=grpc.ssl_channel_credentials()
|
|
55
|
+
)
|
|
56
|
+
else:
|
|
57
|
+
self._channel = grpc.insecure_channel(
|
|
58
|
+
target='{}:{}'.format(self._host, self._port)
|
|
59
|
+
)
|
|
60
|
+
return cluster_pb2_grpc.ClusterServiceStub(self._channel)
|
|
61
|
+
|
|
62
|
+
def resume(self) -> bool:
|
|
63
|
+
"""
|
|
64
|
+
Return True if cluster came to active state else False.
|
|
65
|
+
"""
|
|
66
|
+
with status_lock as lock:
|
|
67
|
+
if lock.is_active:
|
|
68
|
+
print('Cluster is already active')
|
|
69
|
+
return True
|
|
70
|
+
status_payload = cluster_pb2.ClusterStatusRequest(
|
|
71
|
+
user=self._user,
|
|
72
|
+
password=self._password
|
|
73
|
+
)
|
|
74
|
+
current_status = self._get_connection.status(status_payload)
|
|
75
|
+
print('Current status', current_status)
|
|
76
|
+
if current_status.status == 'suspended':
|
|
77
|
+
payload = cluster_pb2.ResumeRequest(
|
|
78
|
+
user=self._user,
|
|
79
|
+
password=self._password
|
|
80
|
+
)
|
|
81
|
+
response = self._get_connection.resume(payload)
|
|
82
|
+
print('resuming response', response.status)
|
|
83
|
+
elif current_status.status == 'active':
|
|
84
|
+
print('Cluster is already active.')
|
|
85
|
+
return True
|
|
86
|
+
elif current_status.status != 'resuming':
|
|
87
|
+
"""
|
|
88
|
+
If cluster is in resuming state already, start watching for the status.
|
|
89
|
+
Cluster is in different state, cannot resume.
|
|
90
|
+
"""
|
|
91
|
+
print('Cluster is in different state, cannot resume.')
|
|
92
|
+
return False
|
|
93
|
+
while True:
|
|
94
|
+
try:
|
|
95
|
+
status_payload = cluster_pb2.ClusterStatusRequest(
|
|
96
|
+
user=self._user,
|
|
97
|
+
password=self._password
|
|
98
|
+
)
|
|
99
|
+
response = self._get_connection.status(status_payload)
|
|
100
|
+
print(response)
|
|
101
|
+
if response.status == 'active':
|
|
102
|
+
lock.set_active()
|
|
103
|
+
print('Breaking because of status:', response.status)
|
|
104
|
+
return True
|
|
105
|
+
if response.status in ['suspended', 'failed']:
|
|
106
|
+
print('Breaking because of status:', response.status)
|
|
107
|
+
return False
|
|
108
|
+
if time.time() > self._timeout:
|
|
109
|
+
print('Breaking because of timeout')
|
|
110
|
+
return False
|
|
111
|
+
except _InactiveRpcError as e:
|
|
112
|
+
print('On resume error', e)
|
|
113
|
+
print('Retrying')
|
|
114
|
+
time.sleep(5)
|
|
115
|
+
|
|
116
|
+
def suspend(self):
|
|
117
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# source: cluster.proto
|
|
4
|
+
"""Generated protocol buffer code."""
|
|
5
|
+
from google.protobuf import descriptor as _descriptor
|
|
6
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
7
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
8
|
+
from google.protobuf.internal import builder as _builder
|
|
9
|
+
# @@protoc_insertion_point(imports)
|
|
10
|
+
|
|
11
|
+
_sym_db = _symbol_database.Default()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\rcluster.proto\"/\n\rResumeRequest\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\" \n\x0eResumeResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\"0\n\x0eSuspendRequest\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\"!\n\x0fSuspendResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\"6\n\x14\x43lusterStatusRequest\x12\x0c\n\x04user\x18\x01 \x01(\t\x12\x10\n\x08password\x18\x02 \x01(\t\"\'\n\x15\x43lusterStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t2\xa2\x01\n\x0e\x43lusterService\x12)\n\x06resume\x12\x0e.ResumeRequest\x1a\x0f.ResumeResponse\x12,\n\x07suspend\x12\x0f.SuspendRequest\x1a\x10.SuspendResponse\x12\x37\n\x06status\x12\x15.ClusterStatusRequest\x1a\x16.ClusterStatusResponseB\x02P\x01\x62\x06proto3')
|
|
17
|
+
|
|
18
|
+
_globals = globals()
|
|
19
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
20
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'cluster_pb2', _globals)
|
|
21
|
+
if _descriptor._USE_C_DESCRIPTORS == False:
|
|
22
|
+
DESCRIPTOR._options = None
|
|
23
|
+
DESCRIPTOR._serialized_options = b'P\001'
|
|
24
|
+
_globals['_RESUMEREQUEST']._serialized_start=17
|
|
25
|
+
_globals['_RESUMEREQUEST']._serialized_end=64
|
|
26
|
+
_globals['_RESUMERESPONSE']._serialized_start=66
|
|
27
|
+
_globals['_RESUMERESPONSE']._serialized_end=98
|
|
28
|
+
_globals['_SUSPENDREQUEST']._serialized_start=100
|
|
29
|
+
_globals['_SUSPENDREQUEST']._serialized_end=148
|
|
30
|
+
_globals['_SUSPENDRESPONSE']._serialized_start=150
|
|
31
|
+
_globals['_SUSPENDRESPONSE']._serialized_end=183
|
|
32
|
+
_globals['_CLUSTERSTATUSREQUEST']._serialized_start=185
|
|
33
|
+
_globals['_CLUSTERSTATUSREQUEST']._serialized_end=239
|
|
34
|
+
_globals['_CLUSTERSTATUSRESPONSE']._serialized_start=241
|
|
35
|
+
_globals['_CLUSTERSTATUSRESPONSE']._serialized_end=280
|
|
36
|
+
_globals['_CLUSTERSERVICE']._serialized_start=283
|
|
37
|
+
_globals['_CLUSTERSERVICE']._serialized_end=445
|
|
38
|
+
# @@protoc_insertion_point(module_scope)
|
e6data_python_connector-2.1.21.dev0/e6data_python_connector/cluster_server/cluster_pb2_grpc.py
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
|
|
5
|
+
import e6data_python_connector.cluster_server.cluster_pb2 as cluster__pb2
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ClusterServiceStub(object):
|
|
9
|
+
"""Missing associated documentation comment in .proto file."""
|
|
10
|
+
|
|
11
|
+
def __init__(self, channel):
|
|
12
|
+
"""Constructor.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
channel: A grpc.Channel.
|
|
16
|
+
"""
|
|
17
|
+
self.resume = channel.unary_unary(
|
|
18
|
+
'/ClusterService/resume',
|
|
19
|
+
request_serializer=cluster__pb2.ResumeRequest.SerializeToString,
|
|
20
|
+
response_deserializer=cluster__pb2.ResumeResponse.FromString,
|
|
21
|
+
)
|
|
22
|
+
self.suspend = channel.unary_unary(
|
|
23
|
+
'/ClusterService/suspend',
|
|
24
|
+
request_serializer=cluster__pb2.SuspendRequest.SerializeToString,
|
|
25
|
+
response_deserializer=cluster__pb2.SuspendResponse.FromString,
|
|
26
|
+
)
|
|
27
|
+
self.status = channel.unary_unary(
|
|
28
|
+
'/ClusterService/status',
|
|
29
|
+
request_serializer=cluster__pb2.ClusterStatusRequest.SerializeToString,
|
|
30
|
+
response_deserializer=cluster__pb2.ClusterStatusResponse.FromString,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ClusterServiceServicer(object):
|
|
35
|
+
"""Missing associated documentation comment in .proto file."""
|
|
36
|
+
|
|
37
|
+
def resume(self, request, context):
|
|
38
|
+
"""Missing associated documentation comment in .proto file."""
|
|
39
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
40
|
+
context.set_details('Method not implemented!')
|
|
41
|
+
raise NotImplementedError('Method not implemented!')
|
|
42
|
+
|
|
43
|
+
def suspend(self, request, context):
|
|
44
|
+
"""Missing associated documentation comment in .proto file."""
|
|
45
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
46
|
+
context.set_details('Method not implemented!')
|
|
47
|
+
raise NotImplementedError('Method not implemented!')
|
|
48
|
+
|
|
49
|
+
def status(self, request, context):
|
|
50
|
+
"""Missing associated documentation comment in .proto file."""
|
|
51
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
52
|
+
context.set_details('Method not implemented!')
|
|
53
|
+
raise NotImplementedError('Method not implemented!')
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def add_ClusterServiceServicer_to_server(servicer, server):
|
|
57
|
+
rpc_method_handlers = {
|
|
58
|
+
'resume': grpc.unary_unary_rpc_method_handler(
|
|
59
|
+
servicer.resume,
|
|
60
|
+
request_deserializer=cluster__pb2.ResumeRequest.FromString,
|
|
61
|
+
response_serializer=cluster__pb2.ResumeResponse.SerializeToString,
|
|
62
|
+
),
|
|
63
|
+
'suspend': grpc.unary_unary_rpc_method_handler(
|
|
64
|
+
servicer.suspend,
|
|
65
|
+
request_deserializer=cluster__pb2.SuspendRequest.FromString,
|
|
66
|
+
response_serializer=cluster__pb2.SuspendResponse.SerializeToString,
|
|
67
|
+
),
|
|
68
|
+
'status': grpc.unary_unary_rpc_method_handler(
|
|
69
|
+
servicer.status,
|
|
70
|
+
request_deserializer=cluster__pb2.ClusterStatusRequest.FromString,
|
|
71
|
+
response_serializer=cluster__pb2.ClusterStatusResponse.SerializeToString,
|
|
72
|
+
),
|
|
73
|
+
}
|
|
74
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
75
|
+
'ClusterService', rpc_method_handlers)
|
|
76
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
# This class is part of an EXPERIMENTAL API.
|
|
80
|
+
class ClusterService(object):
|
|
81
|
+
"""Missing associated documentation comment in .proto file."""
|
|
82
|
+
|
|
83
|
+
@staticmethod
|
|
84
|
+
def resume(request,
|
|
85
|
+
target,
|
|
86
|
+
options=(),
|
|
87
|
+
channel_credentials=None,
|
|
88
|
+
call_credentials=None,
|
|
89
|
+
insecure=False,
|
|
90
|
+
compression=None,
|
|
91
|
+
wait_for_ready=None,
|
|
92
|
+
timeout=None,
|
|
93
|
+
metadata=None):
|
|
94
|
+
return grpc.experimental.unary_unary(request, target, '/ClusterService/resume',
|
|
95
|
+
cluster__pb2.ResumeRequest.SerializeToString,
|
|
96
|
+
cluster__pb2.ResumeResponse.FromString,
|
|
97
|
+
options, channel_credentials,
|
|
98
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def suspend(request,
|
|
102
|
+
target,
|
|
103
|
+
options=(),
|
|
104
|
+
channel_credentials=None,
|
|
105
|
+
call_credentials=None,
|
|
106
|
+
insecure=False,
|
|
107
|
+
compression=None,
|
|
108
|
+
wait_for_ready=None,
|
|
109
|
+
timeout=None,
|
|
110
|
+
metadata=None):
|
|
111
|
+
return grpc.experimental.unary_unary(request, target, '/ClusterService/suspend',
|
|
112
|
+
cluster__pb2.SuspendRequest.SerializeToString,
|
|
113
|
+
cluster__pb2.SuspendResponse.FromString,
|
|
114
|
+
options, channel_credentials,
|
|
115
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
116
|
+
|
|
117
|
+
@staticmethod
|
|
118
|
+
def status(request,
|
|
119
|
+
target,
|
|
120
|
+
options=(),
|
|
121
|
+
channel_credentials=None,
|
|
122
|
+
call_credentials=None,
|
|
123
|
+
insecure=False,
|
|
124
|
+
compression=None,
|
|
125
|
+
wait_for_ready=None,
|
|
126
|
+
timeout=None,
|
|
127
|
+
metadata=None):
|
|
128
|
+
return grpc.experimental.unary_unary(request, target, '/ClusterService/status',
|
|
129
|
+
cluster__pb2.ClusterStatusRequest.SerializeToString,
|
|
130
|
+
cluster__pb2.ClusterStatusResponse.FromString,
|
|
131
|
+
options, channel_credentials,
|
|
132
|
+
insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
|
|
@@ -16,7 +16,9 @@ from io import BytesIO
|
|
|
16
16
|
from ssl import CERT_NONE, CERT_OPTIONAL, CERT_REQUIRED
|
|
17
17
|
|
|
18
18
|
import grpc
|
|
19
|
+
from grpc._channel import _InactiveRpcError
|
|
19
20
|
|
|
21
|
+
from e6data_python_connector.cluster_manager import ClusterManager
|
|
20
22
|
from e6data_python_connector.common import DBAPITypeObject, ParamEscaper, DBAPICursor
|
|
21
23
|
from e6data_python_connector.constants import *
|
|
22
24
|
from e6data_python_connector.datainputstream import get_query_columns_info, read_rows_from_chunk
|
|
@@ -114,6 +116,7 @@ class Connection(object):
|
|
|
114
116
|
database: str = None,
|
|
115
117
|
cluster_uuid: str = None,
|
|
116
118
|
secure: bool = False,
|
|
119
|
+
auto_resume: bool = False,
|
|
117
120
|
grpc_options: dict = None,
|
|
118
121
|
):
|
|
119
122
|
"""
|
|
@@ -137,6 +140,8 @@ class Connection(object):
|
|
|
137
140
|
Cluster's uuid
|
|
138
141
|
secure: bool, Optional
|
|
139
142
|
Flag to use a secure channel for data transfer
|
|
143
|
+
auto_resume: bool, Optional
|
|
144
|
+
Flag to enable auto resume of the cluster before the query execution
|
|
140
145
|
grpc_options: dict, Optional
|
|
141
146
|
Specify gRPC configuration
|
|
142
147
|
- keepalive_timeout_ms: This parameter defines the time, in milliseconds, that a gRPC connection should remain idle before sending a keepalive ping to check if the connection is still alive.
|
|
@@ -160,6 +165,8 @@ class Connection(object):
|
|
|
160
165
|
|
|
161
166
|
self.catalog_name = catalog
|
|
162
167
|
|
|
168
|
+
self._auto_resume = auto_resume
|
|
169
|
+
|
|
163
170
|
self._keepalive_timeout_ms = 900000
|
|
164
171
|
self._max_receive_message_length = -1
|
|
165
172
|
self._max_send_message_length = 300 * 1024 * 1024 # mb
|
|
@@ -208,11 +215,38 @@ class Connection(object):
|
|
|
208
215
|
)
|
|
209
216
|
authenticate_response = self._client.authenticate(
|
|
210
217
|
authenticate_request,
|
|
211
|
-
metadata=_get_grpc_header(cluster=self.cluster_uuid)
|
|
218
|
+
metadata=_get_grpc_header(cluster=self.cluster_uuid),
|
|
219
|
+
# timeout=3
|
|
212
220
|
)
|
|
213
221
|
self._session_id = authenticate_response.sessionId
|
|
214
222
|
if not self._session_id:
|
|
215
223
|
raise ValueError("Invalid credentials.")
|
|
224
|
+
except _InactiveRpcError as e:
|
|
225
|
+
if self._auto_resume:
|
|
226
|
+
if e.code() == grpc.StatusCode.UNKNOWN and 'Stream removed' in e.details():
|
|
227
|
+
status = ClusterManager(
|
|
228
|
+
host=self._host,
|
|
229
|
+
port=self._port,
|
|
230
|
+
user=self.__username,
|
|
231
|
+
password=self.__password,
|
|
232
|
+
secure_channel=self._secure_channel
|
|
233
|
+
).resume()
|
|
234
|
+
if status:
|
|
235
|
+
authenticate_request = e6x_engine_pb2.AuthenticateRequest(
|
|
236
|
+
user=self.__username,
|
|
237
|
+
password=self.__password
|
|
238
|
+
)
|
|
239
|
+
authenticate_response = self._client.authenticate(
|
|
240
|
+
authenticate_request,
|
|
241
|
+
metadata=_get_grpc_header(cluster=self.cluster_uuid)
|
|
242
|
+
)
|
|
243
|
+
self._session_id = authenticate_response.sessionId
|
|
244
|
+
else:
|
|
245
|
+
raise e
|
|
246
|
+
else:
|
|
247
|
+
raise e
|
|
248
|
+
else:
|
|
249
|
+
raise e
|
|
216
250
|
except Exception as e:
|
|
217
251
|
self._channel.close()
|
|
218
252
|
raise e
|
|
@@ -5,6 +5,7 @@ pyproject.toml
|
|
|
5
5
|
setup.cfg
|
|
6
6
|
setup.py
|
|
7
7
|
e6data_python_connector/__init__.py
|
|
8
|
+
e6data_python_connector/cluster_manager.py
|
|
8
9
|
e6data_python_connector/common.py
|
|
9
10
|
e6data_python_connector/constants.py
|
|
10
11
|
e6data_python_connector/datainputstream.py
|
|
@@ -19,6 +20,9 @@ e6data_python_connector.egg-info/dependency_links.txt
|
|
|
19
20
|
e6data_python_connector.egg-info/entry_points.txt
|
|
20
21
|
e6data_python_connector.egg-info/requires.txt
|
|
21
22
|
e6data_python_connector.egg-info/top_level.txt
|
|
23
|
+
e6data_python_connector/cluster_server/__init__.py
|
|
24
|
+
e6data_python_connector/cluster_server/cluster_pb2.py
|
|
25
|
+
e6data_python_connector/cluster_server/cluster_pb2_grpc.py
|
|
22
26
|
e6data_python_connector/e6x_vector/__init__.py
|
|
23
27
|
e6data_python_connector/e6x_vector/constants.py
|
|
24
28
|
e6data_python_connector/e6x_vector/ttypes.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|