e6data-python-connector 2.3.8__tar.gz → 2.3.9__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.3.8/e6data_python_connector.egg-info → e6data_python_connector-2.3.9}/PKG-INFO +2 -2
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/README.md +1 -1
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/dialect.py +3 -1
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6data_grpc.py +61 -37
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/strategy.py +1 -18
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9/e6data_python_connector.egg-info}/PKG-INFO +2 -2
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/setup.py +1 -1
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/LICENSE +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/MANIFEST.in +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/__init__.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_manager.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/__init__.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/common.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/constants.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/datainputstream.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/date_time_utils.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/__init__.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/constants.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/exceptions.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/QueryEngineService.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/__init__.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/constants.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/ttypes.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/typeId.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/entry_points.txt +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/requires.txt +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/top_level.txt +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/pyproject.toml +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/setup.cfg +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/__init__.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_38_nines.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_all_cases.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_binary.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_correct_value.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_fields.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/check_decimal_errors.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/cleanup_test_files.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/debug_38_nines.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/debug_binary.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/final_test.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/move_tests.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/quick_test.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_38_nines.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_all_decimal128_cases.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_efficiency.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_none_strategy.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_strategy.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_comprehensive.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_current_implementation.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_decimal128_binary_parsing.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_decimal128_parsing.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_fix.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_improved_parsing.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_known_case.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_manual_analysis.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_mock_server.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_multiprocessing_fix.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_new_implementation.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_specific_binary.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_logic.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_persistence_fix.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_sharing_fix.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_user_binary_value.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/tests.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/tests_grpc.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/validate_decimal128.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/validate_implementation.py +0 -0
- {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/verify_decimal_fix.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: e6data-python-connector
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.9
|
|
4
4
|
Summary: Client for the e6data distributed SQL Engine.
|
|
5
5
|
Home-page: https://github.com/e6x-labs/e6data-python-connector
|
|
6
6
|
Author: e6data, Inc.
|
|
@@ -38,7 +38,7 @@ Dynamic: summary
|
|
|
38
38
|
|
|
39
39
|
# e6data Python Connector
|
|
40
40
|
|
|
41
|
-

|
|
42
42
|
|
|
43
43
|
## Introduction
|
|
44
44
|
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/dialect.py
RENAMED
|
@@ -229,6 +229,7 @@ class E6dataDialect(default.DefaultDialect):
|
|
|
229
229
|
self.cluster_name = url.query.get("cluster-name")
|
|
230
230
|
self.secure = url.query.get("secure") == "true"
|
|
231
231
|
self.auto_resume = url.query.get("auto-resume", "true") == "true" # default to True
|
|
232
|
+
self.debug = url.query.get("debug", "false") == "true" # default to True
|
|
232
233
|
if not self.catalog_name:
|
|
233
234
|
raise Exception('Please specify catalog in query parameter.')
|
|
234
235
|
|
|
@@ -250,7 +251,8 @@ class E6dataDialect(default.DefaultDialect):
|
|
|
250
251
|
"cluster_name": self.cluster_name,
|
|
251
252
|
'secure': self.secure,
|
|
252
253
|
'auto_resume': self.auto_resume,
|
|
253
|
-
'grpc_options': grpc_options
|
|
254
|
+
'grpc_options': grpc_options,
|
|
255
|
+
'debug': self.debug
|
|
254
256
|
}
|
|
255
257
|
return [], kwargs
|
|
256
258
|
|
|
@@ -128,26 +128,18 @@ _local_strategy_cache = {
|
|
|
128
128
|
# Strategy cache timeout in seconds (5 minutes)
|
|
129
129
|
STRATEGY_CACHE_TIMEOUT = 300
|
|
130
130
|
|
|
131
|
+
# Global set to track debug-enabled connections
|
|
132
|
+
_debug_connections = set()
|
|
133
|
+
|
|
134
|
+
def _strategy_debug_log(message):
|
|
135
|
+
"""Log strategy debug messages if any connection has debug enabled."""
|
|
136
|
+
if _debug_connections:
|
|
137
|
+
print(f"[E6DATA_STRATEGY_DEBUG] {time.strftime('%Y-%m-%d %H:%M:%S')} - {message}")
|
|
138
|
+
|
|
131
139
|
|
|
132
140
|
def _get_shared_strategy():
|
|
133
141
|
"""Get or create the shared strategy storage."""
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# Try to use multiprocessing.Manager for process-safe storage
|
|
137
|
-
try:
|
|
138
|
-
if _strategy_manager is None:
|
|
139
|
-
_strategy_manager = multiprocessing.Manager()
|
|
140
|
-
_shared_strategy = _strategy_manager.dict()
|
|
141
|
-
_shared_strategy['active_strategy'] = None
|
|
142
|
-
_shared_strategy['last_check_time'] = 0
|
|
143
|
-
_shared_strategy['pending_strategy'] = None
|
|
144
|
-
_shared_strategy['query_strategy_map'] = _strategy_manager.dict()
|
|
145
|
-
_shared_strategy['last_transition_time'] = 0
|
|
146
|
-
_shared_strategy['session_invalidated'] = False
|
|
147
|
-
return _shared_strategy
|
|
148
|
-
except:
|
|
149
|
-
# Fall back to thread-local storage if Manager fails
|
|
150
|
-
return _local_strategy_cache
|
|
142
|
+
return _local_strategy_cache
|
|
151
143
|
|
|
152
144
|
|
|
153
145
|
def _get_active_strategy():
|
|
@@ -175,10 +167,14 @@ def _set_active_strategy(strategy):
|
|
|
175
167
|
with _strategy_lock:
|
|
176
168
|
shared_strategy = _get_shared_strategy()
|
|
177
169
|
current_time = time.time()
|
|
170
|
+
old_strategy = shared_strategy.get('active_strategy')
|
|
178
171
|
|
|
179
172
|
# Only update transition time if strategy actually changed
|
|
180
|
-
if
|
|
173
|
+
if old_strategy != normalized_strategy:
|
|
181
174
|
shared_strategy['last_transition_time'] = current_time
|
|
175
|
+
_strategy_debug_log(f"Setting active strategy: {old_strategy} -> {normalized_strategy}")
|
|
176
|
+
else:
|
|
177
|
+
_strategy_debug_log(f"Active strategy unchanged: {normalized_strategy}")
|
|
182
178
|
|
|
183
179
|
shared_strategy['active_strategy'] = normalized_strategy
|
|
184
180
|
shared_strategy['last_check_time'] = current_time
|
|
@@ -188,6 +184,9 @@ def _clear_strategy_cache():
|
|
|
188
184
|
"""Clear the cached strategy to force re-detection."""
|
|
189
185
|
with _strategy_lock:
|
|
190
186
|
shared_strategy = _get_shared_strategy()
|
|
187
|
+
old_strategy = shared_strategy.get('active_strategy')
|
|
188
|
+
if old_strategy:
|
|
189
|
+
_strategy_debug_log(f"Clearing strategy cache (was: {old_strategy})")
|
|
191
190
|
shared_strategy['active_strategy'] = None
|
|
192
191
|
shared_strategy['last_check_time'] = 0
|
|
193
192
|
shared_strategy['pending_strategy'] = None
|
|
@@ -208,6 +207,8 @@ def _set_pending_strategy(strategy):
|
|
|
208
207
|
|
|
209
208
|
if normalized_strategy != current_active:
|
|
210
209
|
shared_strategy['pending_strategy'] = normalized_strategy
|
|
210
|
+
query_count = len(shared_strategy.get('query_strategy_map', {}))
|
|
211
|
+
_strategy_debug_log(f"Setting pending strategy: {normalized_strategy} (current: {current_active}, active queries: {query_count})")
|
|
211
212
|
|
|
212
213
|
|
|
213
214
|
def _apply_pending_strategy():
|
|
@@ -219,11 +220,15 @@ def _apply_pending_strategy():
|
|
|
219
220
|
new_strategy = shared_strategy['pending_strategy']
|
|
220
221
|
current_time = time.time()
|
|
221
222
|
|
|
223
|
+
_strategy_debug_log(f"Applying pending strategy: {old_strategy} -> {new_strategy}")
|
|
224
|
+
|
|
222
225
|
shared_strategy['active_strategy'] = new_strategy
|
|
223
226
|
shared_strategy['pending_strategy'] = None
|
|
224
227
|
shared_strategy['last_check_time'] = current_time
|
|
225
228
|
shared_strategy['last_transition_time'] = current_time
|
|
226
229
|
shared_strategy['session_invalidated'] = True # Invalidate all sessions
|
|
230
|
+
|
|
231
|
+
_strategy_debug_log(f"Strategy transition complete. All sessions invalidated.")
|
|
227
232
|
|
|
228
233
|
return new_strategy
|
|
229
234
|
return None
|
|
@@ -250,6 +255,7 @@ def _register_query_strategy(query_id, strategy):
|
|
|
250
255
|
query_map = shared_strategy.get('query_strategy_map', {})
|
|
251
256
|
query_map[query_id] = normalized_strategy
|
|
252
257
|
shared_strategy['query_strategy_map'] = query_map
|
|
258
|
+
_strategy_debug_log(f"Query {query_id} registered with strategy: {normalized_strategy}")
|
|
253
259
|
|
|
254
260
|
|
|
255
261
|
def _get_query_strategy(query_id):
|
|
@@ -271,8 +277,11 @@ def _cleanup_query_strategy(query_id):
|
|
|
271
277
|
shared_strategy = _get_shared_strategy()
|
|
272
278
|
query_map = shared_strategy.get('query_strategy_map', {})
|
|
273
279
|
if query_id in query_map:
|
|
280
|
+
strategy = query_map[query_id]
|
|
274
281
|
del query_map[query_id]
|
|
275
282
|
shared_strategy['query_strategy_map'] = query_map
|
|
283
|
+
remaining_queries = len(query_map)
|
|
284
|
+
_strategy_debug_log(f"Query {query_id} completed (was using {strategy}). Remaining active queries: {remaining_queries}")
|
|
276
285
|
|
|
277
286
|
|
|
278
287
|
def _get_strategy_debug_info():
|
|
@@ -319,6 +328,7 @@ class Connection(object):
|
|
|
319
328
|
auto_resume: bool = True,
|
|
320
329
|
scheme: str = 'e6data',
|
|
321
330
|
grpc_options: dict = None,
|
|
331
|
+
debug: bool = False,
|
|
322
332
|
):
|
|
323
333
|
"""
|
|
324
334
|
Parameters
|
|
@@ -350,6 +360,8 @@ class Connection(object):
|
|
|
350
360
|
- max_send_message_length: Similar to max_receive_message_length, this parameter sets the maximum allowed size (in bytes) for outgoing messages from the gRPC client
|
|
351
361
|
- grpc_prepare_timeout: Timeout for prepare statement API call (default to 10 minutes).
|
|
352
362
|
- keepalive_time_ms: This parameter defines the time, in milliseconds, Default to 30 seconds
|
|
363
|
+
debug: bool, Optional
|
|
364
|
+
Flag to enable debug logging for blue-green deployment strategy changes
|
|
353
365
|
"""
|
|
354
366
|
if not username or not password:
|
|
355
367
|
raise ValueError("username or password cannot be empty.")
|
|
@@ -379,6 +391,13 @@ class Connection(object):
|
|
|
379
391
|
The default maximum time on client side to wait for the cluster to resume is 5 minutes.
|
|
380
392
|
"""
|
|
381
393
|
self.grpc_auto_resume_timeout_seconds = self._grpc_options.pop('grpc_auto_resume_timeout_seconds')
|
|
394
|
+
|
|
395
|
+
# Store debug flag and register with debug connections
|
|
396
|
+
self._debug = debug
|
|
397
|
+
if self._debug:
|
|
398
|
+
_debug_connections.add(id(self))
|
|
399
|
+
_strategy_debug_log(f"Debug mode enabled for connection {id(self)}")
|
|
400
|
+
|
|
382
401
|
self._create_client()
|
|
383
402
|
|
|
384
403
|
@property
|
|
@@ -505,6 +524,7 @@ class Connection(object):
|
|
|
505
524
|
|
|
506
525
|
if active_strategy and not pending_strategy:
|
|
507
526
|
# Use cached strategy only if there's no pending strategy
|
|
527
|
+
_strategy_debug_log(f"Authenticating with cached strategy: {active_strategy}")
|
|
508
528
|
try:
|
|
509
529
|
authenticate_response = self._client.authenticate(
|
|
510
530
|
authenticate_request,
|
|
@@ -518,10 +538,15 @@ class Connection(object):
|
|
|
518
538
|
new_strategy = authenticate_response.new_strategy.lower()
|
|
519
539
|
if new_strategy != active_strategy:
|
|
520
540
|
_set_pending_strategy(new_strategy)
|
|
521
|
-
|
|
541
|
+
_apply_pending_strategy()
|
|
542
|
+
self._session_id = None
|
|
543
|
+
self.close()
|
|
544
|
+
self._create_client()
|
|
545
|
+
return self.get_session_id
|
|
522
546
|
except _InactiveRpcError as e:
|
|
523
547
|
if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
|
|
524
548
|
# Strategy changed, clear cache and retry
|
|
549
|
+
_strategy_debug_log(f"Got 456 error with strategy {active_strategy}, clearing cache and retrying")
|
|
525
550
|
_clear_strategy_cache()
|
|
526
551
|
active_strategy = None
|
|
527
552
|
else:
|
|
@@ -540,8 +565,10 @@ class Connection(object):
|
|
|
540
565
|
else:
|
|
541
566
|
# Always try blue first, then green if it fails with 456
|
|
542
567
|
strategies = ['blue', 'green']
|
|
568
|
+
_strategy_debug_log(f"No cached strategy, will try strategies in order: {strategies}")
|
|
543
569
|
last_error = None
|
|
544
570
|
for strategy in strategies:
|
|
571
|
+
_strategy_debug_log(f"Attempting authentication with strategy: {strategy}")
|
|
545
572
|
try:
|
|
546
573
|
authenticate_response = self._client.authenticate(
|
|
547
574
|
authenticate_request,
|
|
@@ -550,19 +577,24 @@ class Connection(object):
|
|
|
550
577
|
self._session_id = authenticate_response.sessionId
|
|
551
578
|
if self._session_id:
|
|
552
579
|
# Success! Cache this strategy
|
|
580
|
+
_strategy_debug_log(f"Authentication successful with strategy: {strategy}")
|
|
553
581
|
_set_active_strategy(strategy)
|
|
554
582
|
|
|
555
583
|
# Check for new strategy in authenticate response
|
|
556
|
-
if hasattr(authenticate_response,
|
|
557
|
-
'new_strategy') and authenticate_response.new_strategy:
|
|
584
|
+
if hasattr(authenticate_response, 'new_strategy') and authenticate_response.new_strategy:
|
|
558
585
|
new_strategy = authenticate_response.new_strategy.lower()
|
|
559
586
|
if new_strategy != strategy:
|
|
560
587
|
_set_pending_strategy(new_strategy)
|
|
561
|
-
|
|
588
|
+
_apply_pending_strategy()
|
|
589
|
+
self.close()
|
|
590
|
+
self._create_client()
|
|
591
|
+
self._session_id = None
|
|
592
|
+
return self.get_session_id
|
|
562
593
|
break
|
|
563
594
|
except _InactiveRpcError as e:
|
|
564
595
|
if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
|
|
565
596
|
# Wrong strategy, try the next one
|
|
597
|
+
_strategy_debug_log(f"Strategy {strategy} failed with 456 error, trying next")
|
|
566
598
|
last_error = e
|
|
567
599
|
continue
|
|
568
600
|
else:
|
|
@@ -589,21 +621,6 @@ class Connection(object):
|
|
|
589
621
|
).resume()
|
|
590
622
|
if status:
|
|
591
623
|
return self.get_session_id
|
|
592
|
-
# authenticate_request = e6x_engine_pb2.AuthenticateRequest(
|
|
593
|
-
# user=self.__username,
|
|
594
|
-
# password=self.__password
|
|
595
|
-
# )
|
|
596
|
-
# authenticate_response = self._client.authenticate(
|
|
597
|
-
# authenticate_request,
|
|
598
|
-
# metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=_get_active_strategy())
|
|
599
|
-
# )
|
|
600
|
-
# self._session_id = authenticate_response.sessionId
|
|
601
|
-
# # Check for new strategy in authenticate response
|
|
602
|
-
# if hasattr(authenticate_response, 'new_strategy') and authenticate_response.new_strategy:
|
|
603
|
-
# new_strategy = authenticate_response.new_strategy.lower()
|
|
604
|
-
# if new_strategy != _get_active_strategy():
|
|
605
|
-
# _set_pending_strategy(new_strategy)
|
|
606
|
-
# # Don't apply immediately - let new queries use fresh connections
|
|
607
624
|
else:
|
|
608
625
|
raise e
|
|
609
626
|
else:
|
|
@@ -649,6 +666,11 @@ class Connection(object):
|
|
|
649
666
|
self._channel.close()
|
|
650
667
|
self._channel = None
|
|
651
668
|
self._session_id = None
|
|
669
|
+
|
|
670
|
+
# Remove from debug connections if debug was enabled
|
|
671
|
+
if self._debug:
|
|
672
|
+
_debug_connections.discard(id(self))
|
|
673
|
+
_strategy_debug_log(f"Debug mode disabled for connection {id(self)}")
|
|
652
674
|
|
|
653
675
|
def check_connection(self):
|
|
654
676
|
"""
|
|
@@ -1095,6 +1117,7 @@ class Cursor(DBAPICursor):
|
|
|
1095
1117
|
query_map = shared_strategy.get('query_strategy_map', {})
|
|
1096
1118
|
|
|
1097
1119
|
if pending_strategy and len(query_map) == 0:
|
|
1120
|
+
_strategy_debug_log(f"Last query cleared, triggering pending strategy transition")
|
|
1098
1121
|
_apply_pending_strategy()
|
|
1099
1122
|
|
|
1100
1123
|
return clear_response
|
|
@@ -1118,6 +1141,7 @@ class Cursor(DBAPICursor):
|
|
|
1118
1141
|
query_map = shared_strategy.get('query_strategy_map', {})
|
|
1119
1142
|
|
|
1120
1143
|
if pending_strategy and len(query_map) == 0:
|
|
1144
|
+
_strategy_debug_log(f"Last query cleared, triggering pending strategy transition")
|
|
1121
1145
|
_apply_pending_strategy()
|
|
1122
1146
|
|
|
1123
1147
|
def status(self, query_id):
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/strategy.py
RENAMED
|
@@ -40,24 +40,7 @@ def _initialize_shared_state():
|
|
|
40
40
|
with _initialization_lock:
|
|
41
41
|
if _shared_strategy is not None:
|
|
42
42
|
return _shared_strategy
|
|
43
|
-
|
|
44
|
-
try:
|
|
45
|
-
# Try to create multiprocessing Manager
|
|
46
|
-
_manager = multiprocessing.Manager()
|
|
47
|
-
_shared_strategy = _manager.dict({
|
|
48
|
-
'active_strategy': None,
|
|
49
|
-
'last_check_time': 0,
|
|
50
|
-
'pending_strategy': None,
|
|
51
|
-
'query_strategy_map': _manager.dict(),
|
|
52
|
-
'last_transition_time': 0,
|
|
53
|
-
'session_invalidated': False
|
|
54
|
-
})
|
|
55
|
-
_logger.debug("Successfully initialized multiprocessing Manager for strategy sharing")
|
|
56
|
-
return _shared_strategy
|
|
57
|
-
except Exception as e:
|
|
58
|
-
# Fall back to thread-local storage if Manager fails
|
|
59
|
-
_logger.warning(f"Failed to initialize multiprocessing Manager: {e}. Using thread-local storage.")
|
|
60
|
-
return _local_strategy_cache
|
|
43
|
+
return _local_strategy_cache
|
|
61
44
|
|
|
62
45
|
|
|
63
46
|
def _get_shared_strategy():
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: e6data-python-connector
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.9
|
|
4
4
|
Summary: Client for the e6data distributed SQL Engine.
|
|
5
5
|
Home-page: https://github.com/e6x-labs/e6data-python-connector
|
|
6
6
|
Author: e6data, Inc.
|
|
@@ -38,7 +38,7 @@ Dynamic: summary
|
|
|
38
38
|
|
|
39
39
|
# e6data Python Connector
|
|
40
40
|
|
|
41
|
-

|
|
42
42
|
|
|
43
43
|
## Introduction
|
|
44
44
|
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/common.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/constants.py
RENAMED
|
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
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/typeId.py
RENAMED
|
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
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_correct_value.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/check_decimal_errors.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_all_decimal128_cases.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_current_implementation.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_decimal128_parsing.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_improved_parsing.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_manual_analysis.py
RENAMED
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_multiprocessing_fix.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_new_implementation.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_specific_binary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_sharing_fix.py
RENAMED
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_user_binary_value.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/validate_implementation.py
RENAMED
|
File without changes
|
|
File without changes
|