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.
Files changed (77) hide show
  1. {e6data_python_connector-2.3.8/e6data_python_connector.egg-info → e6data_python_connector-2.3.9}/PKG-INFO +2 -2
  2. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/README.md +1 -1
  3. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/dialect.py +3 -1
  4. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6data_grpc.py +61 -37
  5. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/strategy.py +1 -18
  6. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9/e6data_python_connector.egg-info}/PKG-INFO +2 -2
  7. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/setup.py +1 -1
  8. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/LICENSE +0 -0
  9. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/MANIFEST.in +0 -0
  10. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/__init__.py +0 -0
  11. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_manager.py +0 -0
  12. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/__init__.py +0 -0
  13. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/cluster_pb2.py +0 -0
  14. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/cluster_server/cluster_pb2_grpc.py +0 -0
  15. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/common.py +0 -0
  16. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/constants.py +0 -0
  17. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/datainputstream.py +0 -0
  18. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/date_time_utils.py +0 -0
  19. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/__init__.py +0 -0
  20. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/constants.py +0 -0
  21. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/e6x_vector/ttypes.py +0 -0
  22. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/exceptions.py +0 -0
  23. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/QueryEngineService.py +0 -0
  24. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/__init__.py +0 -0
  25. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/constants.py +0 -0
  26. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2.py +0 -0
  27. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2.pyi +0 -0
  28. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/e6x_engine_pb2_grpc.py +0 -0
  29. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/server/ttypes.py +0 -0
  30. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector/typeId.py +0 -0
  31. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/SOURCES.txt +0 -0
  32. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/dependency_links.txt +0 -0
  33. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/entry_points.txt +0 -0
  34. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/requires.txt +0 -0
  35. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/e6data_python_connector.egg-info/top_level.txt +0 -0
  36. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/pyproject.toml +0 -0
  37. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/setup.cfg +0 -0
  38. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/__init__.py +0 -0
  39. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_38_nines.py +0 -0
  40. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_all_cases.py +0 -0
  41. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_binary.py +0 -0
  42. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_correct_value.py +0 -0
  43. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/analyze_fields.py +0 -0
  44. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/check_decimal_errors.py +0 -0
  45. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/cleanup_test_files.py +0 -0
  46. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/debug_38_nines.py +0 -0
  47. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/debug_binary.py +0 -0
  48. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/final_test.py +0 -0
  49. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/move_tests.py +0 -0
  50. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/quick_test.py +0 -0
  51. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_38_nines.py +0 -0
  52. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_all_decimal128_cases.py +0 -0
  53. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_efficiency.py +0 -0
  54. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_none_strategy.py +0 -0
  55. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_cluster_manager_strategy.py +0 -0
  56. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_comprehensive.py +0 -0
  57. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_current_implementation.py +0 -0
  58. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_decimal128_binary_parsing.py +0 -0
  59. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_decimal128_parsing.py +0 -0
  60. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_fix.py +0 -0
  61. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_improved_parsing.py +0 -0
  62. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_known_case.py +0 -0
  63. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_manual_analysis.py +0 -0
  64. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_mock_server.py +0 -0
  65. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_multiprocessing_fix.py +0 -0
  66. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_new_implementation.py +0 -0
  67. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_specific_binary.py +0 -0
  68. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy.py +0 -0
  69. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_logic.py +0 -0
  70. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_persistence_fix.py +0 -0
  71. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_strategy_sharing_fix.py +0 -0
  72. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/test_user_binary_value.py +0 -0
  73. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/tests.py +0 -0
  74. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/tests_grpc.py +0 -0
  75. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/validate_decimal128.py +0 -0
  76. {e6data_python_connector-2.3.8 → e6data_python_connector-2.3.9}/test/validate_implementation.py +0 -0
  77. {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.8
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
- ![version](https://img.shields.io/badge/version-2.3.8-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9-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.8-blue.svg)
3
+ ![version](https://img.shields.io/badge/version-2.3.9-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,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
- 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
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 shared_strategy['active_strategy'] != normalized_strategy:
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
- # Don't apply immediately - let new queries use fresh connections
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
- # Don't apply immediately - let new queries use fresh connections
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):
@@ -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.8
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
- ![version](https://img.shields.io/badge/version-2.3.8-blue.svg)
41
+ ![version](https://img.shields.io/badge/version-2.3.9-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, 8,)
15
+ VERSION = (2, 3, 9,)
16
16
 
17
17
 
18
18
  def get_long_desc():