exonware-xwnode 0.0.1.12__py3-none-any.whl

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 (132) hide show
  1. exonware/__init__.py +14 -0
  2. exonware/xwnode/__init__.py +127 -0
  3. exonware/xwnode/base.py +676 -0
  4. exonware/xwnode/config.py +178 -0
  5. exonware/xwnode/contracts.py +730 -0
  6. exonware/xwnode/errors.py +503 -0
  7. exonware/xwnode/facade.py +460 -0
  8. exonware/xwnode/strategies/__init__.py +158 -0
  9. exonware/xwnode/strategies/advisor.py +463 -0
  10. exonware/xwnode/strategies/edges/__init__.py +32 -0
  11. exonware/xwnode/strategies/edges/adj_list.py +227 -0
  12. exonware/xwnode/strategies/edges/adj_matrix.py +391 -0
  13. exonware/xwnode/strategies/edges/base.py +169 -0
  14. exonware/xwnode/strategies/flyweight.py +328 -0
  15. exonware/xwnode/strategies/impls/__init__.py +13 -0
  16. exonware/xwnode/strategies/impls/_base_edge.py +403 -0
  17. exonware/xwnode/strategies/impls/_base_node.py +307 -0
  18. exonware/xwnode/strategies/impls/edge_adj_list.py +353 -0
  19. exonware/xwnode/strategies/impls/edge_adj_matrix.py +445 -0
  20. exonware/xwnode/strategies/impls/edge_bidir_wrapper.py +455 -0
  21. exonware/xwnode/strategies/impls/edge_block_adj_matrix.py +539 -0
  22. exonware/xwnode/strategies/impls/edge_coo.py +533 -0
  23. exonware/xwnode/strategies/impls/edge_csc.py +447 -0
  24. exonware/xwnode/strategies/impls/edge_csr.py +492 -0
  25. exonware/xwnode/strategies/impls/edge_dynamic_adj_list.py +503 -0
  26. exonware/xwnode/strategies/impls/edge_flow_network.py +555 -0
  27. exonware/xwnode/strategies/impls/edge_hyperedge_set.py +516 -0
  28. exonware/xwnode/strategies/impls/edge_neural_graph.py +650 -0
  29. exonware/xwnode/strategies/impls/edge_octree.py +574 -0
  30. exonware/xwnode/strategies/impls/edge_property_store.py +655 -0
  31. exonware/xwnode/strategies/impls/edge_quadtree.py +519 -0
  32. exonware/xwnode/strategies/impls/edge_rtree.py +820 -0
  33. exonware/xwnode/strategies/impls/edge_temporal_edgeset.py +558 -0
  34. exonware/xwnode/strategies/impls/edge_tree_graph_basic.py +271 -0
  35. exonware/xwnode/strategies/impls/edge_weighted_graph.py +411 -0
  36. exonware/xwnode/strategies/manager.py +775 -0
  37. exonware/xwnode/strategies/metrics.py +538 -0
  38. exonware/xwnode/strategies/migration.py +432 -0
  39. exonware/xwnode/strategies/nodes/__init__.py +50 -0
  40. exonware/xwnode/strategies/nodes/_base_node.py +307 -0
  41. exonware/xwnode/strategies/nodes/adjacency_list.py +267 -0
  42. exonware/xwnode/strategies/nodes/aho_corasick.py +345 -0
  43. exonware/xwnode/strategies/nodes/array_list.py +209 -0
  44. exonware/xwnode/strategies/nodes/base.py +247 -0
  45. exonware/xwnode/strategies/nodes/deque.py +200 -0
  46. exonware/xwnode/strategies/nodes/hash_map.py +135 -0
  47. exonware/xwnode/strategies/nodes/heap.py +307 -0
  48. exonware/xwnode/strategies/nodes/linked_list.py +232 -0
  49. exonware/xwnode/strategies/nodes/node_aho_corasick.py +520 -0
  50. exonware/xwnode/strategies/nodes/node_array_list.py +175 -0
  51. exonware/xwnode/strategies/nodes/node_avl_tree.py +371 -0
  52. exonware/xwnode/strategies/nodes/node_b_plus_tree.py +542 -0
  53. exonware/xwnode/strategies/nodes/node_bitmap.py +420 -0
  54. exonware/xwnode/strategies/nodes/node_bitset_dynamic.py +513 -0
  55. exonware/xwnode/strategies/nodes/node_bloom_filter.py +347 -0
  56. exonware/xwnode/strategies/nodes/node_btree.py +357 -0
  57. exonware/xwnode/strategies/nodes/node_count_min_sketch.py +470 -0
  58. exonware/xwnode/strategies/nodes/node_cow_tree.py +473 -0
  59. exonware/xwnode/strategies/nodes/node_cuckoo_hash.py +392 -0
  60. exonware/xwnode/strategies/nodes/node_fenwick_tree.py +301 -0
  61. exonware/xwnode/strategies/nodes/node_hash_map.py +269 -0
  62. exonware/xwnode/strategies/nodes/node_heap.py +191 -0
  63. exonware/xwnode/strategies/nodes/node_hyperloglog.py +407 -0
  64. exonware/xwnode/strategies/nodes/node_linked_list.py +409 -0
  65. exonware/xwnode/strategies/nodes/node_lsm_tree.py +400 -0
  66. exonware/xwnode/strategies/nodes/node_ordered_map.py +390 -0
  67. exonware/xwnode/strategies/nodes/node_ordered_map_balanced.py +565 -0
  68. exonware/xwnode/strategies/nodes/node_patricia.py +512 -0
  69. exonware/xwnode/strategies/nodes/node_persistent_tree.py +378 -0
  70. exonware/xwnode/strategies/nodes/node_radix_trie.py +452 -0
  71. exonware/xwnode/strategies/nodes/node_red_black_tree.py +497 -0
  72. exonware/xwnode/strategies/nodes/node_roaring_bitmap.py +570 -0
  73. exonware/xwnode/strategies/nodes/node_segment_tree.py +289 -0
  74. exonware/xwnode/strategies/nodes/node_set_hash.py +354 -0
  75. exonware/xwnode/strategies/nodes/node_set_tree.py +480 -0
  76. exonware/xwnode/strategies/nodes/node_skip_list.py +316 -0
  77. exonware/xwnode/strategies/nodes/node_splay_tree.py +393 -0
  78. exonware/xwnode/strategies/nodes/node_suffix_array.py +487 -0
  79. exonware/xwnode/strategies/nodes/node_treap.py +387 -0
  80. exonware/xwnode/strategies/nodes/node_tree_graph_hybrid.py +1434 -0
  81. exonware/xwnode/strategies/nodes/node_trie.py +252 -0
  82. exonware/xwnode/strategies/nodes/node_union_find.py +187 -0
  83. exonware/xwnode/strategies/nodes/node_xdata_optimized.py +369 -0
  84. exonware/xwnode/strategies/nodes/priority_queue.py +209 -0
  85. exonware/xwnode/strategies/nodes/queue.py +161 -0
  86. exonware/xwnode/strategies/nodes/sparse_matrix.py +206 -0
  87. exonware/xwnode/strategies/nodes/stack.py +152 -0
  88. exonware/xwnode/strategies/nodes/trie.py +274 -0
  89. exonware/xwnode/strategies/nodes/union_find.py +283 -0
  90. exonware/xwnode/strategies/pattern_detector.py +603 -0
  91. exonware/xwnode/strategies/performance_monitor.py +487 -0
  92. exonware/xwnode/strategies/queries/__init__.py +24 -0
  93. exonware/xwnode/strategies/queries/base.py +236 -0
  94. exonware/xwnode/strategies/queries/cql.py +201 -0
  95. exonware/xwnode/strategies/queries/cypher.py +181 -0
  96. exonware/xwnode/strategies/queries/datalog.py +70 -0
  97. exonware/xwnode/strategies/queries/elastic_dsl.py +70 -0
  98. exonware/xwnode/strategies/queries/eql.py +70 -0
  99. exonware/xwnode/strategies/queries/flux.py +70 -0
  100. exonware/xwnode/strategies/queries/gql.py +70 -0
  101. exonware/xwnode/strategies/queries/graphql.py +240 -0
  102. exonware/xwnode/strategies/queries/gremlin.py +181 -0
  103. exonware/xwnode/strategies/queries/hiveql.py +214 -0
  104. exonware/xwnode/strategies/queries/hql.py +70 -0
  105. exonware/xwnode/strategies/queries/jmespath.py +219 -0
  106. exonware/xwnode/strategies/queries/jq.py +66 -0
  107. exonware/xwnode/strategies/queries/json_query.py +66 -0
  108. exonware/xwnode/strategies/queries/jsoniq.py +248 -0
  109. exonware/xwnode/strategies/queries/kql.py +70 -0
  110. exonware/xwnode/strategies/queries/linq.py +238 -0
  111. exonware/xwnode/strategies/queries/logql.py +70 -0
  112. exonware/xwnode/strategies/queries/mql.py +68 -0
  113. exonware/xwnode/strategies/queries/n1ql.py +210 -0
  114. exonware/xwnode/strategies/queries/partiql.py +70 -0
  115. exonware/xwnode/strategies/queries/pig.py +215 -0
  116. exonware/xwnode/strategies/queries/promql.py +70 -0
  117. exonware/xwnode/strategies/queries/sparql.py +220 -0
  118. exonware/xwnode/strategies/queries/sql.py +275 -0
  119. exonware/xwnode/strategies/queries/xml_query.py +66 -0
  120. exonware/xwnode/strategies/queries/xpath.py +223 -0
  121. exonware/xwnode/strategies/queries/xquery.py +258 -0
  122. exonware/xwnode/strategies/queries/xwnode_executor.py +332 -0
  123. exonware/xwnode/strategies/queries/xwquery_strategy.py +424 -0
  124. exonware/xwnode/strategies/registry.py +604 -0
  125. exonware/xwnode/strategies/simple.py +273 -0
  126. exonware/xwnode/strategies/utils.py +532 -0
  127. exonware/xwnode/types.py +912 -0
  128. exonware/xwnode/version.py +78 -0
  129. exonware_xwnode-0.0.1.12.dist-info/METADATA +169 -0
  130. exonware_xwnode-0.0.1.12.dist-info/RECORD +132 -0
  131. exonware_xwnode-0.0.1.12.dist-info/WHEEL +4 -0
  132. exonware_xwnode-0.0.1.12.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,487 @@
1
+ #!/usr/bin/env python3
2
+ #exonware/xwnode/src/exonware/xwnode/strategies/performance_monitor.py
3
+ """
4
+ Strategy Performance Monitor
5
+
6
+ Tracks strategy usage, performance metrics, and provides optimization recommendations.
7
+ This enables data-driven strategy selection and performance tuning.
8
+
9
+ Company: eXonware.com
10
+ Author: Eng. Muhammad AlShehri
11
+ Email: connect@exonware.com
12
+ Version: 0.0.1.12
13
+ Generation Date: 07-Sep-2025
14
+ """
15
+
16
+ import time
17
+ import threading
18
+ from typing import Any, Dict, List, Optional, Tuple, Union
19
+ from dataclasses import dataclass, field
20
+ from collections import defaultdict, deque
21
+ from enum import Enum
22
+ from exonware.xwsystem import get_logger
23
+
24
+ logger = get_logger(__name__)
25
+
26
+ from ..types import NodeMode, EdgeMode
27
+
28
+
29
+
30
+ class OperationType(Enum):
31
+ """Types of operations to monitor."""
32
+ GET = "get"
33
+ PUT = "put"
34
+ DELETE = "delete"
35
+ ITERATE = "iterate"
36
+ SEARCH = "search"
37
+ MIGRATE = "migrate"
38
+ CREATE = "create"
39
+
40
+
41
+ @dataclass
42
+ class OperationMetrics:
43
+ """Metrics for a specific operation."""
44
+ operation: OperationType
45
+ count: int = 0
46
+ total_time: float = 0.0
47
+ min_time: float = float('inf')
48
+ max_time: float = 0.0
49
+ avg_time: float = 0.0
50
+ error_count: int = 0
51
+ memory_usage: float = 0.0
52
+
53
+ def add_measurement(self, duration: float, memory_usage: float = 0.0, error: bool = False):
54
+ """Add a new measurement."""
55
+ self.count += 1
56
+ self.total_time += duration
57
+ self.min_time = min(self.min_time, duration)
58
+ self.max_time = max(self.max_time, duration)
59
+ self.avg_time = self.total_time / self.count
60
+ self.memory_usage += memory_usage
61
+
62
+ if error:
63
+ self.error_count += 1
64
+
65
+
66
+ @dataclass
67
+ class StrategyProfile:
68
+ """Performance profile for a strategy."""
69
+ strategy_name: str
70
+ mode: Union[NodeMode, EdgeMode]
71
+ total_operations: int = 0
72
+ total_time: float = 0.0
73
+ operations: Dict[OperationType, OperationMetrics] = field(default_factory=dict)
74
+ memory_usage: float = 0.0
75
+ error_rate: float = 0.0
76
+ last_used: float = 0.0
77
+ creation_time: float = field(default_factory=time.time)
78
+
79
+ def get_operation_metrics(self, operation: OperationType) -> OperationMetrics:
80
+ """Get or create operation metrics."""
81
+ if operation not in self.operations:
82
+ self.operations[operation] = OperationMetrics(operation)
83
+ return self.operations[operation]
84
+
85
+ def update_error_rate(self):
86
+ """Update error rate calculation."""
87
+ total_errors = sum(op.error_count for op in self.operations.values())
88
+ self.error_rate = total_errors / max(self.total_operations, 1)
89
+
90
+
91
+ @dataclass
92
+ class PerformanceRecommendation:
93
+ """Performance optimization recommendation."""
94
+ strategy_name: str
95
+ recommendation_type: str
96
+ confidence: float
97
+ reasoning: str
98
+ estimated_improvement: float
99
+ alternative_strategy: Optional[str] = None
100
+
101
+
102
+ class StrategyPerformanceMonitor:
103
+ """
104
+ Monitors strategy performance and provides optimization recommendations.
105
+ """
106
+
107
+ def __init__(self, history_size: int = 1000):
108
+ """
109
+ Initialize performance monitor.
110
+
111
+ Args:
112
+ history_size: Maximum number of operations to keep in history
113
+ """
114
+ self._history_size = history_size
115
+ self._profiles: Dict[str, StrategyProfile] = {}
116
+ self._operation_history: deque = deque(maxlen=history_size)
117
+ self._lock = threading.RLock()
118
+ self._stats = {
119
+ 'total_operations': 0,
120
+ 'total_strategies': 0,
121
+ 'monitoring_start_time': time.time(),
122
+ 'recommendations_given': 0
123
+ }
124
+
125
+ def record_operation(
126
+ self,
127
+ strategy_id: str,
128
+ operation: OperationType,
129
+ duration: float,
130
+ memory_usage: float = 0.0,
131
+ error: bool = False,
132
+ **metadata: Any
133
+ ) -> None:
134
+ """
135
+ Record an operation for performance monitoring.
136
+
137
+ Args:
138
+ strategy_id: Unique identifier for the strategy
139
+ operation: Type of operation performed
140
+ duration: Operation duration in seconds
141
+ memory_usage: Memory usage in bytes
142
+ error: Whether the operation resulted in an error
143
+ **metadata: Additional metadata
144
+ """
145
+ with self._lock:
146
+ # Get or create strategy profile
147
+ if strategy_id not in self._profiles:
148
+ self._profiles[strategy_id] = StrategyProfile(
149
+ strategy_name=strategy_id,
150
+ mode=self._extract_mode_from_id(strategy_id)
151
+ )
152
+ self._stats['total_strategies'] += 1
153
+
154
+ profile = self._profiles[strategy_id]
155
+
156
+ # Update profile
157
+ profile.total_operations += 1
158
+ profile.total_time += duration
159
+ profile.memory_usage += memory_usage
160
+ profile.last_used = time.time()
161
+
162
+ # Update operation metrics
163
+ op_metrics = profile.get_operation_metrics(operation)
164
+ op_metrics.add_measurement(duration, memory_usage, error)
165
+
166
+ # Update error rate
167
+ profile.update_error_rate()
168
+
169
+ # Add to history
170
+ self._operation_history.append({
171
+ 'timestamp': time.time(),
172
+ 'strategy_id': strategy_id,
173
+ 'operation': operation.value,
174
+ 'duration': duration,
175
+ 'memory_usage': memory_usage,
176
+ 'error': error,
177
+ 'metadata': metadata
178
+ })
179
+
180
+ self._stats['total_operations'] += 1
181
+
182
+ logger.debug(f"๐Ÿ“Š Recorded {operation.value} operation for {strategy_id}: {duration:.3f}s")
183
+
184
+ def get_strategy_profile(self, strategy_id: str) -> Optional[StrategyProfile]:
185
+ """
186
+ Get performance profile for a strategy.
187
+
188
+ Args:
189
+ strategy_id: Strategy identifier
190
+
191
+ Returns:
192
+ Strategy profile or None if not found
193
+ """
194
+ with self._lock:
195
+ return self._profiles.get(strategy_id)
196
+
197
+ def get_top_performing_strategies(self, limit: int = 5) -> List[Tuple[str, StrategyProfile]]:
198
+ """
199
+ Get top performing strategies by average operation time.
200
+
201
+ Args:
202
+ limit: Maximum number of strategies to return
203
+
204
+ Returns:
205
+ List of (strategy_id, profile) tuples sorted by performance
206
+ """
207
+ with self._lock:
208
+ strategies = []
209
+ for strategy_id, profile in self._profiles.items():
210
+ if profile.total_operations > 0:
211
+ avg_time = profile.total_time / profile.total_operations
212
+ strategies.append((strategy_id, profile, avg_time))
213
+
214
+ # Sort by average time (lower is better)
215
+ strategies.sort(key=lambda x: x[2])
216
+
217
+ return [(sid, prof) for sid, prof, _ in strategies[:limit]]
218
+
219
+ def get_underperforming_strategies(self, threshold: float = 0.1) -> List[Tuple[str, StrategyProfile]]:
220
+ """
221
+ Get strategies that are underperforming.
222
+
223
+ Args:
224
+ threshold: Error rate threshold for underperformance
225
+
226
+ Returns:
227
+ List of underperforming strategies
228
+ """
229
+ with self._lock:
230
+ underperforming = []
231
+ for strategy_id, profile in self._profiles.items():
232
+ if profile.error_rate > threshold or profile.total_operations == 0:
233
+ underperforming.append((strategy_id, profile))
234
+
235
+ return underperforming
236
+
237
+ def generate_recommendations(self, strategy_id: str) -> List[PerformanceRecommendation]:
238
+ """
239
+ Generate performance recommendations for a strategy.
240
+
241
+ Args:
242
+ strategy_id: Strategy identifier
243
+
244
+ Returns:
245
+ List of performance recommendations
246
+ """
247
+ profile = self.get_strategy_profile(strategy_id)
248
+ if not profile or profile.total_operations < 10:
249
+ return []
250
+
251
+ recommendations = []
252
+
253
+ # Check for high error rate
254
+ if profile.error_rate > 0.05: # 5% error rate
255
+ recommendations.append(PerformanceRecommendation(
256
+ strategy_name=strategy_id,
257
+ recommendation_type="error_rate",
258
+ confidence=0.8,
259
+ reasoning=f"High error rate ({profile.error_rate:.1%}) detected",
260
+ estimated_improvement=0.2,
261
+ alternative_strategy=self._suggest_alternative_strategy(profile.mode)
262
+ ))
263
+
264
+ # Check for slow operations
265
+ slow_operations = []
266
+ for op_type, metrics in profile.operations.items():
267
+ if metrics.avg_time > 0.01: # 10ms threshold
268
+ slow_operations.append((op_type, metrics.avg_time))
269
+
270
+ if slow_operations:
271
+ slowest_op, slowest_time = max(slow_operations, key=lambda x: x[1])
272
+ recommendations.append(PerformanceRecommendation(
273
+ strategy_name=strategy_id,
274
+ recommendation_type="slow_operations",
275
+ confidence=0.7,
276
+ reasoning=f"Slow {slowest_op.value} operations (avg: {slowest_time:.3f}s)",
277
+ estimated_improvement=0.3,
278
+ alternative_strategy=self._suggest_alternative_strategy(profile.mode)
279
+ ))
280
+
281
+ # Check for memory usage
282
+ if profile.memory_usage > 100 * 1024 * 1024: # 100MB threshold
283
+ recommendations.append(PerformanceRecommendation(
284
+ strategy_name=strategy_id,
285
+ recommendation_type="memory_usage",
286
+ confidence=0.6,
287
+ reasoning=f"High memory usage ({profile.memory_usage / 1024 / 1024:.1f}MB)",
288
+ estimated_improvement=0.4,
289
+ alternative_strategy=self._suggest_memory_efficient_strategy(profile.mode)
290
+ ))
291
+
292
+ # Check for unused strategies
293
+ time_since_last_use = time.time() - profile.last_used
294
+ if time_since_last_use > 3600: # 1 hour
295
+ recommendations.append(PerformanceRecommendation(
296
+ strategy_name=strategy_id,
297
+ recommendation_type="unused_strategy",
298
+ confidence=0.9,
299
+ reasoning=f"Strategy unused for {time_since_last_use / 3600:.1f} hours",
300
+ estimated_improvement=0.1,
301
+ alternative_strategy="Consider removing unused strategy"
302
+ ))
303
+
304
+ self._stats['recommendations_given'] += len(recommendations)
305
+ return recommendations
306
+
307
+ def get_performance_summary(self) -> Dict[str, Any]:
308
+ """
309
+ Get overall performance summary.
310
+
311
+ Returns:
312
+ Performance summary dictionary
313
+ """
314
+ with self._lock:
315
+ if not self._profiles:
316
+ return {
317
+ 'total_strategies': 0,
318
+ 'total_operations': 0,
319
+ 'average_operation_time': 0.0,
320
+ 'total_error_rate': 0.0,
321
+ 'monitoring_duration': 0.0
322
+ }
323
+
324
+ total_operations = sum(p.total_operations for p in self._profiles.values())
325
+ total_time = sum(p.total_time for p in self._profiles.values())
326
+ total_errors = sum(
327
+ sum(op.error_count for op in p.operations.values())
328
+ for p in self._profiles.values()
329
+ )
330
+
331
+ avg_operation_time = total_time / total_operations if total_operations > 0 else 0.0
332
+ total_error_rate = total_errors / total_operations if total_operations > 0 else 0.0
333
+ monitoring_duration = time.time() - self._stats['monitoring_start_time']
334
+
335
+ return {
336
+ 'total_strategies': len(self._profiles),
337
+ 'total_operations': total_operations,
338
+ 'average_operation_time': avg_operation_time,
339
+ 'total_error_rate': total_error_rate,
340
+ 'monitoring_duration': monitoring_duration,
341
+ 'operations_per_second': total_operations / monitoring_duration if monitoring_duration > 0 else 0.0,
342
+ 'top_strategies': [
343
+ {
344
+ 'strategy_id': sid,
345
+ 'operations': prof.total_operations,
346
+ 'avg_time': prof.total_time / prof.total_operations if prof.total_operations > 0 else 0.0,
347
+ 'error_rate': prof.error_rate
348
+ }
349
+ for sid, prof in self.get_top_performing_strategies(3)
350
+ ]
351
+ }
352
+
353
+ def get_operation_history(self, limit: int = 100) -> List[Dict[str, Any]]:
354
+ """
355
+ Get recent operation history.
356
+
357
+ Args:
358
+ limit: Maximum number of operations to return
359
+
360
+ Returns:
361
+ List of recent operations
362
+ """
363
+ with self._lock:
364
+ return list(self._operation_history)[-limit:]
365
+
366
+ def clear_history(self) -> None:
367
+ """Clear operation history."""
368
+ with self._lock:
369
+ self._operation_history.clear()
370
+ logger.info("๐Ÿงน Cleared performance monitoring history")
371
+
372
+ def reset_stats(self) -> None:
373
+ """Reset all statistics."""
374
+ with self._lock:
375
+ self._profiles.clear()
376
+ self._operation_history.clear()
377
+ self._stats = {
378
+ 'total_operations': 0,
379
+ 'total_strategies': 0,
380
+ 'monitoring_start_time': time.time(),
381
+ 'recommendations_given': 0
382
+ }
383
+ logger.info("๐Ÿ”„ Reset performance monitoring statistics")
384
+
385
+ def _extract_mode_from_id(self, strategy_id: str) -> Union[NodeMode, EdgeMode]:
386
+ """Extract mode from strategy ID."""
387
+ # Try to extract mode from strategy ID
388
+ for mode in list(NodeMode) + list(EdgeMode):
389
+ if mode.name.lower() in strategy_id.lower():
390
+ return mode
391
+
392
+ # Default fallback
393
+ return NodeMode.HASH_MAP
394
+
395
+ def _suggest_alternative_strategy(self, current_mode: Union[NodeMode, EdgeMode]) -> str:
396
+ """Suggest alternative strategy based on current mode."""
397
+ alternatives = {
398
+ NodeMode.HASH_MAP: "ARRAY_LIST or TREE_GRAPH_HYBRID",
399
+ NodeMode.ARRAY_LIST: "HASH_MAP or TREE_GRAPH_HYBRID",
400
+ NodeMode.TREE_GRAPH_HYBRID: "HASH_MAP or DATA_OPTIMIZED",
401
+ NodeMode.DATA_OPTIMIZED: "HASH_MAP or TREE_GRAPH_HYBRID",
402
+ EdgeMode.ADJ_LIST: "ADJACENCY_MATRIX",
403
+ EdgeMode.ADJACENCY_MATRIX: "adjacency_list"
404
+ }
405
+
406
+ return alternatives.get(current_mode, "Unknown alternative")
407
+
408
+ def _suggest_memory_efficient_strategy(self, current_mode: Union[NodeMode, EdgeMode]) -> str:
409
+ """Suggest memory-efficient alternative strategy."""
410
+ memory_efficient = {
411
+ NodeMode.HASH_MAP: "ARRAY_LIST (for sequential data)",
412
+ NodeMode.ARRAY_LIST: "HASH_MAP (for sparse data)",
413
+ NodeMode.TREE_GRAPH_HYBRID: "DATA_OPTIMIZED (for large datasets)",
414
+ NodeMode.DATA_OPTIMIZED: "HASH_MAP (for small datasets)",
415
+ EdgeMode.ADJ_LIST: "ADJACENCY_MATRIX (for dense graphs)",
416
+ EdgeMode.ADJACENCY_MATRIX: "adjacency_list (for sparse graphs)"
417
+ }
418
+
419
+ return memory_efficient.get(current_mode, "Consider data structure optimization")
420
+
421
+
422
+ # Global monitor instance
423
+ _monitor_instance: Optional[StrategyPerformanceMonitor] = None
424
+ _monitor_lock = threading.Lock()
425
+
426
+
427
+ def get_monitor() -> StrategyPerformanceMonitor:
428
+ """
429
+ Get the global performance monitor instance.
430
+
431
+ Returns:
432
+ Global StrategyPerformanceMonitor instance
433
+ """
434
+ global _monitor_instance
435
+
436
+ if _monitor_instance is None:
437
+ with _monitor_lock:
438
+ if _monitor_instance is None:
439
+ _monitor_instance = StrategyPerformanceMonitor()
440
+ logger.info("๐Ÿ“Š Initialized global strategy performance monitor")
441
+
442
+ return _monitor_instance
443
+
444
+
445
+ def record_operation(
446
+ strategy_id: str,
447
+ operation: OperationType,
448
+ duration: float,
449
+ memory_usage: float = 0.0,
450
+ error: bool = False,
451
+ **metadata: Any
452
+ ) -> None:
453
+ """
454
+ Record an operation using the global monitor.
455
+
456
+ Args:
457
+ strategy_id: Strategy identifier
458
+ operation: Operation type
459
+ duration: Operation duration
460
+ memory_usage: Memory usage
461
+ error: Whether operation failed
462
+ **metadata: Additional metadata
463
+ """
464
+ get_monitor().record_operation(strategy_id, operation, duration, memory_usage, error, **metadata)
465
+
466
+
467
+ def get_performance_summary() -> Dict[str, Any]:
468
+ """
469
+ Get performance summary from global monitor.
470
+
471
+ Returns:
472
+ Performance summary
473
+ """
474
+ return get_monitor().get_performance_summary()
475
+
476
+
477
+ def get_strategy_recommendations(strategy_id: str) -> List[PerformanceRecommendation]:
478
+ """
479
+ Get recommendations for a strategy from global monitor.
480
+
481
+ Args:
482
+ strategy_id: Strategy identifier
483
+
484
+ Returns:
485
+ List of recommendations
486
+ """
487
+ return get_monitor().generate_recommendations(strategy_id)
@@ -0,0 +1,24 @@
1
+ """
2
+ Query Strategies Package
3
+
4
+ This package contains all query strategy implementations organized by type:
5
+ - Linear queries (index-based, value-based)
6
+ - Tree queries (key-based, range queries)
7
+ - Graph queries (path queries, neighbor queries)
8
+
9
+ Company: eXonware.com
10
+ Author: Eng. Muhammad AlShehri
11
+ Email: connect@exonware.com
12
+ Version: 0.0.1.12
13
+ Generation Date: January 2, 2025
14
+ """
15
+
16
+ from .base import AQueryStrategy
17
+ from .xwquery_strategy import XWQueryScriptStrategy
18
+ from .xwnode_executor import XWNodeQueryActionExecutor
19
+
20
+ __all__ = [
21
+ 'AQueryStrategy',
22
+ 'XWQueryScriptStrategy',
23
+ 'XWNodeQueryActionExecutor'
24
+ ]