e6data-python-connector 2.3.9rc5__tar.gz → 2.3.9rc6__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.
Files changed (77) hide show
  1. {e6data_python_connector-2.3.9rc5/e6data_python_connector.egg-info → e6data_python_connector-2.3.9rc6}/PKG-INFO +2 -2
  2. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/README.md +1 -1
  3. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/cluster_manager.py +2 -16
  4. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/e6data_grpc.py +46 -36
  5. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/strategy.py +33 -17
  6. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6/e6data_python_connector.egg-info}/PKG-INFO +2 -2
  7. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/setup.py +1 -1
  8. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/LICENSE +0 -0
  9. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/MANIFEST.in +0 -0
  10. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/__init__.py +0 -0
  11. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/cluster_server/__init__.py +0 -0
  12. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  13. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  14. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/common.py +0 -0
  15. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/constants.py +0 -0
  16. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/datainputstream.py +0 -0
  17. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/date_time_utils.py +0 -0
  18. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/dialect.py +0 -0
  19. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  20. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/e6x_vector/constants.py +0 -0
  21. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  22. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/exceptions.py +0 -0
  23. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/QueryEngineService.py +0 -0
  24. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/__init__.py +0 -0
  25. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/constants.py +0 -0
  26. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  27. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  28. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  29. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/server/ttypes.py +0 -0
  30. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector/typeId.py +0 -0
  31. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
  32. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  33. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  34. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector.egg-info/requires.txt +0 -0
  35. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/e6data_python_connector.egg-info/top_level.txt +0 -0
  36. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/pyproject.toml +0 -0
  37. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/setup.cfg +0 -0
  38. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/__init__.py +0 -0
  39. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/analyze_38_nines.py +0 -0
  40. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/analyze_all_cases.py +0 -0
  41. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/analyze_binary.py +0 -0
  42. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/analyze_correct_value.py +0 -0
  43. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/analyze_fields.py +0 -0
  44. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/check_decimal_errors.py +0 -0
  45. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/cleanup_test_files.py +0 -0
  46. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/debug_38_nines.py +0 -0
  47. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/debug_binary.py +0 -0
  48. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/final_test.py +0 -0
  49. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/move_tests.py +0 -0
  50. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/quick_test.py +0 -0
  51. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_38_nines.py +0 -0
  52. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_all_decimal128_cases.py +0 -0
  53. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_cluster_manager_efficiency.py +0 -0
  54. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_cluster_manager_none_strategy.py +0 -0
  55. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_cluster_manager_strategy.py +0 -0
  56. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_comprehensive.py +0 -0
  57. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_current_implementation.py +0 -0
  58. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_decimal128_binary_parsing.py +0 -0
  59. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_decimal128_parsing.py +0 -0
  60. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_fix.py +0 -0
  61. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_improved_parsing.py +0 -0
  62. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_known_case.py +0 -0
  63. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_manual_analysis.py +0 -0
  64. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_mock_server.py +0 -0
  65. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_multiprocessing_fix.py +0 -0
  66. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_new_implementation.py +0 -0
  67. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_specific_binary.py +0 -0
  68. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_strategy.py +0 -0
  69. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_strategy_logic.py +0 -0
  70. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_strategy_persistence_fix.py +0 -0
  71. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_strategy_sharing_fix.py +0 -0
  72. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/test_user_binary_value.py +0 -0
  73. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/tests.py +0 -0
  74. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/tests_grpc.py +0 -0
  75. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/validate_decimal128.py +0 -0
  76. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/test/validate_implementation.py +0 -0
  77. {e6data_python_connector-2.3.9rc5 → e6data_python_connector-2.3.9rc6}/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.9rc5
3
+ Version: 2.3.9rc6
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
- ![version](https://img.shields.io/badge/version-2.3.9rc5-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9rc6-blue.svg)
42
42
 
43
43
  ## Introduction
44
44
 
@@ -1,6 +1,6 @@
1
1
  # e6data Python Connector
2
2
 
3
- ![version](https://img.shields.io/badge/version-2.3.9rc5-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.3.9rc6-blue.svg)
4
4
 
5
5
  ## Introduction
6
6
 
@@ -213,30 +213,25 @@ class ClusterManager:
213
213
  user=self._user,
214
214
  password=self._password
215
215
  )
216
- print('STATUS', payload)
217
216
  elif request_type == "resume":
218
217
  payload = cluster_pb2.ResumeRequest(
219
218
  user=self._user,
220
219
  password=self._password
221
220
  )
222
- print('RESUME', payload)
223
221
 
224
222
  # If we have an active strategy, use it first
225
223
  if current_strategy is not None:
226
224
  try:
227
225
  if request_type == "status":
228
-
229
226
  response = self._get_connection.status(
230
227
  payload,
231
228
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=current_strategy)
232
229
  )
233
- print('STATUS 2', response, payload)
234
230
  elif request_type == "resume":
235
231
  response = self._get_connection.resume(
236
232
  payload,
237
233
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=current_strategy)
238
234
  )
239
- print('RESUME 2', response, payload)
240
235
  else:
241
236
  raise ValueError(f"Unknown request type: {request_type}")
242
237
 
@@ -259,13 +254,11 @@ class ClusterManager:
259
254
  payload,
260
255
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=alternative_strategy)
261
256
  )
262
- print('STATUS 3', response, payload)
263
257
  elif request_type == "resume":
264
258
  response = self._get_connection.resume(
265
259
  payload,
266
260
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=alternative_strategy)
267
261
  )
268
- print('RESUME 3', response, payload)
269
262
 
270
263
  # Update active strategy since the alternative worked
271
264
  _set_active_strategy(alternative_strategy)
@@ -295,13 +288,11 @@ class ClusterManager:
295
288
  payload,
296
289
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=strategy)
297
290
  )
298
- print('STATUS 4', response, payload)
299
291
  elif request_type == "resume":
300
292
  response = self._get_connection.resume(
301
293
  payload,
302
294
  metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=strategy)
303
295
  )
304
- print('RESUME 4', response, payload)
305
296
  else:
306
297
  raise ValueError(f"Unknown request type: {request_type}")
307
298
 
@@ -374,15 +365,13 @@ class ClusterManager:
374
365
  # Retrieve the current cluster status with strategy header
375
366
  try:
376
367
  current_status = self._try_cluster_request("status")
377
- except _InactiveRpcError as e:
378
- print('ERROR', e, 'Returning false1')
368
+ except _InactiveRpcError:
379
369
  return False
380
370
  if current_status.status == 'suspended':
381
371
  # Send the resume request with strategy header
382
372
  try:
383
373
  response = self._try_cluster_request("resume")
384
- except _InactiveRpcError as e:
385
- print('ERROR', e, 'Returning false2')
374
+ except _InactiveRpcError:
386
375
  return False
387
376
  elif current_status.status == 'active':
388
377
  return True
@@ -391,18 +380,15 @@ class ClusterManager:
391
380
  If cluster cannot be resumed due to its current state,
392
381
  or already in a process of resuming, terminate the operation.
393
382
  """
394
- print('ERROR', '!resuming', 'Returning false3')
395
383
  return False
396
384
 
397
385
  for status in self._check_cluster_status():
398
386
  if status == 'active':
399
387
  return True
400
388
  elif status == 'failed' or time.time() > self._timeout:
401
- print('ERROR', 'timed-out', 'Returning false3')
402
389
  return False
403
390
  # Wait for 5 seconds before the next status check
404
391
  time.sleep(5)
405
- print('ERROR', 'Nothing worked', 'Returning false3')
406
392
  return False
407
393
 
408
394
  def suspend(self):
@@ -7,6 +7,7 @@ from __future__ import absolute_import
7
7
  from __future__ import unicode_literals
8
8
 
9
9
  import datetime
10
+ import logging
10
11
  import re
11
12
  import sys
12
13
  import time
@@ -27,6 +28,9 @@ from e6data_python_connector.datainputstream import get_query_columns_info, read
27
28
  from e6data_python_connector.server import e6x_engine_pb2_grpc, e6x_engine_pb2
28
29
  from e6data_python_connector.typeId import *
29
30
 
31
+ # Set up logging
32
+ logger = logging.getLogger(__name__)
33
+
30
34
  apilevel = '2.0'
31
35
  threadsafety = 2 # Threads may share the e6xdb and connections.
32
36
  paramstyle = 'pyformat' # Python extended format codes, e.g. ...WHERE name=%(name)s
@@ -134,20 +138,20 @@ def _get_shared_strategy():
134
138
  global _strategy_manager, _shared_strategy
135
139
 
136
140
  # 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
141
+ # try:
142
+ # if _strategy_manager is None:
143
+ # _strategy_manager = multiprocessing.Manager()
144
+ # _shared_strategy = _strategy_manager.dict()
145
+ # _shared_strategy['active_strategy'] = None
146
+ # _shared_strategy['last_check_time'] = 0
147
+ # _shared_strategy['pending_strategy'] = None
148
+ # _shared_strategy['query_strategy_map'] = _strategy_manager.dict()
149
+ # _shared_strategy['last_transition_time'] = 0
150
+ # _shared_strategy['session_invalidated'] = False
151
+ # return _shared_strategy
152
+ # except:
153
+ # # Fall back to thread-local storage if Manager fails
154
+ return _local_strategy_cache
151
155
 
152
156
 
153
157
  def _get_active_strategy():
@@ -177,8 +181,11 @@ def _set_active_strategy(strategy):
177
181
  current_time = time.time()
178
182
 
179
183
  # Only update transition time if strategy actually changed
180
- if shared_strategy['active_strategy'] != normalized_strategy:
184
+ old_strategy = shared_strategy['active_strategy']
185
+ if old_strategy != normalized_strategy:
181
186
  shared_strategy['last_transition_time'] = current_time
187
+ # Debug log for strategy switches
188
+ logger.debug(f"Strategy switched from {old_strategy} to {normalized_strategy}")
182
189
 
183
190
  shared_strategy['active_strategy'] = normalized_strategy
184
191
  shared_strategy['last_check_time'] = current_time
@@ -207,7 +214,12 @@ def _set_pending_strategy(strategy):
207
214
  current_active = shared_strategy['active_strategy']
208
215
 
209
216
  if normalized_strategy != current_active:
217
+ old_pending = shared_strategy.get('pending_strategy')
210
218
  shared_strategy['pending_strategy'] = normalized_strategy
219
+
220
+ # Debug log for pending strategy changes
221
+ if old_pending != normalized_strategy:
222
+ logger.debug(f"Pending strategy changed from {old_pending} to {normalized_strategy}")
211
223
 
212
224
 
213
225
  def _apply_pending_strategy():
@@ -219,12 +231,15 @@ def _apply_pending_strategy():
219
231
  new_strategy = shared_strategy['pending_strategy']
220
232
  current_time = time.time()
221
233
 
234
+ logger.debug(f"Strategy transition initiated: {old_strategy} -> {new_strategy}")
235
+
222
236
  shared_strategy['active_strategy'] = new_strategy
223
237
  shared_strategy['pending_strategy'] = None
224
238
  shared_strategy['last_check_time'] = current_time
225
239
  shared_strategy['last_transition_time'] = current_time
226
240
  shared_strategy['session_invalidated'] = True # Invalidate all sessions
227
241
 
242
+ logger.debug(f"Strategy successfully applied and sessions invalidated")
228
243
  return new_strategy
229
244
  return None
230
245
 
@@ -380,7 +395,6 @@ class Connection(object):
380
395
  """
381
396
  self.grpc_auto_resume_timeout_seconds = self._grpc_options.pop('grpc_auto_resume_timeout_seconds')
382
397
  self._create_client()
383
- self._hash = str(datetime.datetime.now().timestamp()) + 'hash' + str(id(self))
384
398
 
385
399
  @property
386
400
  def _get_grpc_options(self):
@@ -521,7 +535,6 @@ class Connection(object):
521
535
  _set_pending_strategy(new_strategy)
522
536
  # Don't apply immediately - let new queries use fresh connections
523
537
  except _InactiveRpcError as e:
524
- print(self._hash, self.cluster_name, 'Error during authentication with active strategy:', active_strategy, file=sys.stderr)
525
538
  if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
526
539
  # Strategy changed, clear cache and retry
527
540
  _clear_strategy_cache()
@@ -563,7 +576,6 @@ class Connection(object):
563
576
  # Don't apply immediately - let new queries use fresh connections
564
577
  break
565
578
  except _InactiveRpcError as e:
566
- print(self._hash, self.cluster_name, 'Error during authentication with strategy:', strategy, file=sys.stderr)
567
579
  if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
568
580
  # Wrong strategy, try the next one
569
581
  last_error = e
@@ -590,24 +602,23 @@ class Connection(object):
590
602
  cluster_uuid=self.cluster_name,
591
603
  timeout=self.grpc_auto_resume_timeout_seconds
592
604
  ).resume()
593
- print(self._hash, self.cluster_name, 'Cluster resume status:', status, file=sys.stderr)
594
605
  if status:
595
- # return self.get_session_id
596
- authenticate_request = e6x_engine_pb2.AuthenticateRequest(
597
- user=self.__username,
598
- password=self.__password
599
- )
600
- authenticate_response = self._client.authenticate(
601
- authenticate_request,
602
- metadata=_get_grpc_header(cluster=self.cluster_name, strategy=_get_active_strategy())
603
- )
604
- self._session_id = authenticate_response.sessionId
605
- # Check for new strategy in authenticate response
606
- if hasattr(authenticate_response, 'new_strategy') and authenticate_response.new_strategy:
607
- new_strategy = authenticate_response.new_strategy.lower()
608
- if new_strategy != _get_active_strategy():
609
- _set_pending_strategy(new_strategy)
610
- # Don't apply immediately - let new queries use fresh connections
606
+ return self.get_session_id
607
+ # authenticate_request = e6x_engine_pb2.AuthenticateRequest(
608
+ # user=self.__username,
609
+ # password=self.__password
610
+ # )
611
+ # authenticate_response = self._client.authenticate(
612
+ # authenticate_request,
613
+ # metadata=_get_grpc_header(cluster=self.cluster_uuid, strategy=_get_active_strategy())
614
+ # )
615
+ # self._session_id = authenticate_response.sessionId
616
+ # # Check for new strategy in authenticate response
617
+ # if hasattr(authenticate_response, 'new_strategy') and authenticate_response.new_strategy:
618
+ # new_strategy = authenticate_response.new_strategy.lower()
619
+ # if new_strategy != _get_active_strategy():
620
+ # _set_pending_strategy(new_strategy)
621
+ # # Don't apply immediately - let new queries use fresh connections
611
622
  else:
612
623
  raise e
613
624
  else:
@@ -615,7 +626,6 @@ class Connection(object):
615
626
  else:
616
627
  raise e
617
628
  except Exception as e:
618
- print(self._hash, self.cluster_name, 'Error during authentication:', e, file=sys.stderr)
619
629
  self._channel.close()
620
630
  raise e
621
631
  return self._session_id
@@ -41,23 +41,23 @@ def _initialize_shared_state():
41
41
  if _shared_strategy is not None:
42
42
  return _shared_strategy
43
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
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
61
61
 
62
62
 
63
63
  def _get_shared_strategy():
@@ -85,8 +85,14 @@ def _set_active_strategy(strategy):
85
85
  _logger.warning(f"Invalid strategy value: {strategy}. Must be 'blue' or 'green'.")
86
86
  return
87
87
 
88
+ old_strategy = shared_strategy.get('active_strategy')
88
89
  shared_strategy['active_strategy'] = normalized_strategy
89
90
  shared_strategy['last_check_time'] = time.time()
91
+
92
+ # Debug log for strategy switches
93
+ if old_strategy != normalized_strategy:
94
+ _logger.debug(f"Strategy switched from {old_strategy} to {normalized_strategy}")
95
+
90
96
  _logger.info(f"Active deployment strategy set to: {normalized_strategy}")
91
97
 
92
98
 
@@ -105,7 +111,13 @@ def _set_pending_strategy(strategy):
105
111
 
106
112
  current_active = shared_strategy.get('active_strategy')
107
113
  if normalized_strategy != current_active:
114
+ old_pending = shared_strategy.get('pending_strategy')
108
115
  shared_strategy['pending_strategy'] = normalized_strategy
116
+
117
+ # Debug log for pending strategy changes
118
+ if old_pending != normalized_strategy:
119
+ _logger.debug(f"Pending strategy changed from {old_pending} to {normalized_strategy}")
120
+
109
121
  _logger.info(f"Pending deployment strategy set to: {normalized_strategy}")
110
122
 
111
123
 
@@ -160,11 +172,15 @@ def _apply_pending_strategy():
160
172
  if len(query_map) == 0:
161
173
  # No active queries, safe to transition
162
174
  _logger.info(f"Last query completed, applying pending strategy: {pending_strategy}")
175
+ _logger.debug(f"Strategy transition initiated: {active_strategy} -> {pending_strategy}")
176
+
163
177
  shared_strategy['active_strategy'] = pending_strategy
164
178
  shared_strategy['pending_strategy'] = None
165
179
  shared_strategy['last_transition_time'] = time.time()
166
180
  shared_strategy['session_invalidated'] = True # Invalidate all sessions
181
+
167
182
  _logger.info(f"Strategy transition completed: {active_strategy} -> {pending_strategy}")
183
+ _logger.debug(f"Strategy successfully applied and sessions invalidated")
168
184
 
169
185
 
170
186
  def _is_strategy_cache_valid():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: e6data-python-connector
3
- Version: 2.3.9rc5
3
+ Version: 2.3.9rc6
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
- ![version](https://img.shields.io/badge/version-2.3.9rc5-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9rc6-blue.svg)
42
42
 
43
43
  ## Introduction
44
44
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  import setuptools
14
14
 
15
- VERSION = (2, 3, 9,'rc5')
15
+ VERSION = (2, 3, 9,'rc6')
16
16
 
17
17
 
18
18
  def get_long_desc():