e6data-python-connector 2.3.9rc8__tar.gz → 2.3.9rc9__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.9rc8/e6data_python_connector.egg-info → e6data_python_connector-2.3.9rc9}/PKG-INFO +2 -2
  2. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/README.md +1 -1
  3. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/dialect.py +3 -1
  4. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/e6data_grpc.py +51 -17
  5. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/strategy.py +1 -18
  6. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9/e6data_python_connector.egg-info}/PKG-INFO +2 -2
  7. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/setup.py +1 -1
  8. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/LICENSE +0 -0
  9. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/MANIFEST.in +0 -0
  10. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/__init__.py +0 -0
  11. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/cluster_manager.py +0 -0
  12. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/cluster_server/__init__.py +0 -0
  13. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  14. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  15. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/common.py +0 -0
  16. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/constants.py +0 -0
  17. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/datainputstream.py +0 -0
  18. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/date_time_utils.py +0 -0
  19. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  20. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/e6x_vector/constants.py +0 -0
  21. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  22. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/exceptions.py +0 -0
  23. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/QueryEngineService.py +0 -0
  24. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/__init__.py +0 -0
  25. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/constants.py +0 -0
  26. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  27. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  28. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  29. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/server/ttypes.py +0 -0
  30. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector/typeId.py +0 -0
  31. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
  32. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  33. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  34. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector.egg-info/requires.txt +0 -0
  35. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/e6data_python_connector.egg-info/top_level.txt +0 -0
  36. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/pyproject.toml +0 -0
  37. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/setup.cfg +0 -0
  38. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/__init__.py +0 -0
  39. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/analyze_38_nines.py +0 -0
  40. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/analyze_all_cases.py +0 -0
  41. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/analyze_binary.py +0 -0
  42. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/analyze_correct_value.py +0 -0
  43. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/analyze_fields.py +0 -0
  44. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/check_decimal_errors.py +0 -0
  45. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/cleanup_test_files.py +0 -0
  46. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/debug_38_nines.py +0 -0
  47. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/debug_binary.py +0 -0
  48. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/final_test.py +0 -0
  49. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/move_tests.py +0 -0
  50. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/quick_test.py +0 -0
  51. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_38_nines.py +0 -0
  52. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_all_decimal128_cases.py +0 -0
  53. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_cluster_manager_efficiency.py +0 -0
  54. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_cluster_manager_none_strategy.py +0 -0
  55. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_cluster_manager_strategy.py +0 -0
  56. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_comprehensive.py +0 -0
  57. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_current_implementation.py +0 -0
  58. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_decimal128_binary_parsing.py +0 -0
  59. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_decimal128_parsing.py +0 -0
  60. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_fix.py +0 -0
  61. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_improved_parsing.py +0 -0
  62. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_known_case.py +0 -0
  63. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_manual_analysis.py +0 -0
  64. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_mock_server.py +0 -0
  65. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_multiprocessing_fix.py +0 -0
  66. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_new_implementation.py +0 -0
  67. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_specific_binary.py +0 -0
  68. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_strategy.py +0 -0
  69. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_strategy_logic.py +0 -0
  70. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_strategy_persistence_fix.py +0 -0
  71. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_strategy_sharing_fix.py +0 -0
  72. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/test_user_binary_value.py +0 -0
  73. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/tests.py +0 -0
  74. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/tests_grpc.py +0 -0
  75. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/validate_decimal128.py +0 -0
  76. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/test/validate_implementation.py +0 -0
  77. {e6data_python_connector-2.3.9rc8 → e6data_python_connector-2.3.9rc9}/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.9rc8
3
+ Version: 2.3.9rc9
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.9.rc8-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9.rc9-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.9.rc8-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.3.9.rc9-blue.svg)
4
4
 
5
5
  ## Introduction
6
6
 
@@ -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,19 @@ _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
142
  global _strategy_manager, _shared_strategy
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
143
+ return _local_strategy_cache
151
144
 
152
145
 
153
146
  def _get_active_strategy():
@@ -175,10 +168,14 @@ def _set_active_strategy(strategy):
175
168
  with _strategy_lock:
176
169
  shared_strategy = _get_shared_strategy()
177
170
  current_time = time.time()
171
+ old_strategy = shared_strategy.get('active_strategy')
178
172
 
179
173
  # Only update transition time if strategy actually changed
180
- if shared_strategy['active_strategy'] != normalized_strategy:
174
+ if old_strategy != normalized_strategy:
181
175
  shared_strategy['last_transition_time'] = current_time
176
+ _strategy_debug_log(f"Setting active strategy: {old_strategy} -> {normalized_strategy}")
177
+ else:
178
+ _strategy_debug_log(f"Active strategy unchanged: {normalized_strategy}")
182
179
 
183
180
  shared_strategy['active_strategy'] = normalized_strategy
184
181
  shared_strategy['last_check_time'] = current_time
@@ -188,6 +185,9 @@ def _clear_strategy_cache():
188
185
  """Clear the cached strategy to force re-detection."""
189
186
  with _strategy_lock:
190
187
  shared_strategy = _get_shared_strategy()
188
+ old_strategy = shared_strategy.get('active_strategy')
189
+ if old_strategy:
190
+ _strategy_debug_log(f"Clearing strategy cache (was: {old_strategy})")
191
191
  shared_strategy['active_strategy'] = None
192
192
  shared_strategy['last_check_time'] = 0
193
193
  shared_strategy['pending_strategy'] = None
@@ -208,6 +208,8 @@ def _set_pending_strategy(strategy):
208
208
 
209
209
  if normalized_strategy != current_active:
210
210
  shared_strategy['pending_strategy'] = normalized_strategy
211
+ query_count = len(shared_strategy.get('query_strategy_map', {}))
212
+ _strategy_debug_log(f"Setting pending strategy: {normalized_strategy} (current: {current_active}, active queries: {query_count})")
211
213
 
212
214
 
213
215
  def _apply_pending_strategy():
@@ -215,14 +217,19 @@ def _apply_pending_strategy():
215
217
  with _strategy_lock:
216
218
  shared_strategy = _get_shared_strategy()
217
219
  if shared_strategy['pending_strategy']:
220
+ old_strategy = shared_strategy['active_strategy']
218
221
  new_strategy = shared_strategy['pending_strategy']
219
222
  current_time = time.time()
220
223
 
224
+ _strategy_debug_log(f"Applying pending strategy: {old_strategy} -> {new_strategy}")
225
+
221
226
  shared_strategy['active_strategy'] = new_strategy
222
227
  shared_strategy['pending_strategy'] = None
223
228
  shared_strategy['last_check_time'] = current_time
224
229
  shared_strategy['last_transition_time'] = current_time
225
230
  shared_strategy['session_invalidated'] = True # Invalidate all sessions
231
+
232
+ _strategy_debug_log(f"Strategy transition complete. All sessions invalidated.")
226
233
 
227
234
  return new_strategy
228
235
  return None
@@ -249,6 +256,7 @@ def _register_query_strategy(query_id, strategy):
249
256
  query_map = shared_strategy.get('query_strategy_map', {})
250
257
  query_map[query_id] = normalized_strategy
251
258
  shared_strategy['query_strategy_map'] = query_map
259
+ _strategy_debug_log(f"Query {query_id} registered with strategy: {normalized_strategy}")
252
260
 
253
261
 
254
262
  def _get_query_strategy(query_id):
@@ -270,8 +278,11 @@ def _cleanup_query_strategy(query_id):
270
278
  shared_strategy = _get_shared_strategy()
271
279
  query_map = shared_strategy.get('query_strategy_map', {})
272
280
  if query_id in query_map:
281
+ strategy = query_map[query_id]
273
282
  del query_map[query_id]
274
283
  shared_strategy['query_strategy_map'] = query_map
284
+ remaining_queries = len(query_map)
285
+ _strategy_debug_log(f"Query {query_id} completed (was using {strategy}). Remaining active queries: {remaining_queries}")
275
286
 
276
287
 
277
288
  def _get_strategy_debug_info():
@@ -318,6 +329,7 @@ class Connection(object):
318
329
  auto_resume: bool = True,
319
330
  scheme: str = 'e6data',
320
331
  grpc_options: dict = None,
332
+ debug: bool = False,
321
333
  ):
322
334
  """
323
335
  Parameters
@@ -349,6 +361,8 @@ class Connection(object):
349
361
  - 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
350
362
  - grpc_prepare_timeout: Timeout for prepare statement API call (default to 10 minutes).
351
363
  - keepalive_time_ms: This parameter defines the time, in milliseconds, Default to 30 seconds
364
+ debug: bool, Optional
365
+ Flag to enable debug logging for blue-green deployment strategy changes
352
366
  """
353
367
  if not username or not password:
354
368
  raise ValueError("username or password cannot be empty.")
@@ -378,6 +392,13 @@ class Connection(object):
378
392
  The default maximum time on client side to wait for the cluster to resume is 5 minutes.
379
393
  """
380
394
  self.grpc_auto_resume_timeout_seconds = self._grpc_options.pop('grpc_auto_resume_timeout_seconds')
395
+
396
+ # Store debug flag and register with debug connections
397
+ self._debug = debug
398
+ if self._debug:
399
+ _debug_connections.add(id(self))
400
+ _strategy_debug_log(f"Debug mode enabled for connection {id(self)}")
401
+
381
402
  self._create_client()
382
403
 
383
404
  @property
@@ -504,6 +525,7 @@ class Connection(object):
504
525
 
505
526
  if active_strategy and not pending_strategy:
506
527
  # Use cached strategy only if there's no pending strategy
528
+ _strategy_debug_log(f"Authenticating with cached strategy: {active_strategy}")
507
529
  try:
508
530
  authenticate_response = self._client.authenticate(
509
531
  authenticate_request,
@@ -525,6 +547,7 @@ class Connection(object):
525
547
  except _InactiveRpcError as e:
526
548
  if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
527
549
  # Strategy changed, clear cache and retry
550
+ _strategy_debug_log(f"Got 456 error with strategy {active_strategy}, clearing cache and retrying")
528
551
  _clear_strategy_cache()
529
552
  active_strategy = None
530
553
  else:
@@ -543,8 +566,10 @@ class Connection(object):
543
566
  else:
544
567
  # Always try blue first, then green if it fails with 456
545
568
  strategies = ['blue', 'green']
569
+ _strategy_debug_log(f"No cached strategy, will try strategies in order: {strategies}")
546
570
  last_error = None
547
571
  for strategy in strategies:
572
+ _strategy_debug_log(f"Attempting authentication with strategy: {strategy}")
548
573
  try:
549
574
  authenticate_response = self._client.authenticate(
550
575
  authenticate_request,
@@ -553,6 +578,7 @@ class Connection(object):
553
578
  self._session_id = authenticate_response.sessionId
554
579
  if self._session_id:
555
580
  # Success! Cache this strategy
581
+ _strategy_debug_log(f"Authentication successful with strategy: {strategy}")
556
582
  _set_active_strategy(strategy)
557
583
 
558
584
  # Check for new strategy in authenticate response
@@ -569,6 +595,7 @@ class Connection(object):
569
595
  except _InactiveRpcError as e:
570
596
  if e.code() == grpc.StatusCode.UNKNOWN and 'status: 456' in e.details():
571
597
  # Wrong strategy, try the next one
598
+ _strategy_debug_log(f"Strategy {strategy} failed with 456 error, trying next")
572
599
  last_error = e
573
600
  continue
574
601
  else:
@@ -640,6 +667,11 @@ class Connection(object):
640
667
  self._channel.close()
641
668
  self._channel = None
642
669
  self._session_id = None
670
+
671
+ # Remove from debug connections if debug was enabled
672
+ if self._debug:
673
+ _debug_connections.discard(id(self))
674
+ _strategy_debug_log(f"Debug mode disabled for connection {id(self)}")
643
675
 
644
676
  def check_connection(self):
645
677
  """
@@ -1086,6 +1118,7 @@ class Cursor(DBAPICursor):
1086
1118
  query_map = shared_strategy.get('query_strategy_map', {})
1087
1119
 
1088
1120
  if pending_strategy and len(query_map) == 0:
1121
+ _strategy_debug_log(f"Last query cleared, triggering pending strategy transition")
1089
1122
  _apply_pending_strategy()
1090
1123
 
1091
1124
  return clear_response
@@ -1109,6 +1142,7 @@ class Cursor(DBAPICursor):
1109
1142
  query_map = shared_strategy.get('query_strategy_map', {})
1110
1143
 
1111
1144
  if pending_strategy and len(query_map) == 0:
1145
+ _strategy_debug_log(f"Last query cleared, triggering pending strategy transition")
1112
1146
  _apply_pending_strategy()
1113
1147
 
1114
1148
  def status(self, query_id):
@@ -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.9rc8
3
+ Version: 2.3.9rc9
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.9.rc8-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9.rc9-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, 'rc8')
15
+ VERSION = (2, 3, 9, 'rc9')
16
16
 
17
17
 
18
18
  def get_long_desc():