kailash 0.8.4__py3-none-any.whl → 0.8.5__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 (79) hide show
  1. kailash/__init__.py +1 -7
  2. kailash/cli/__init__.py +11 -1
  3. kailash/cli/validation_audit.py +570 -0
  4. kailash/core/actors/supervisor.py +1 -1
  5. kailash/core/resilience/circuit_breaker.py +71 -1
  6. kailash/core/resilience/health_monitor.py +172 -0
  7. kailash/edge/compliance.py +33 -0
  8. kailash/edge/consistency.py +609 -0
  9. kailash/edge/coordination/__init__.py +30 -0
  10. kailash/edge/coordination/global_ordering.py +355 -0
  11. kailash/edge/coordination/leader_election.py +217 -0
  12. kailash/edge/coordination/partition_detector.py +296 -0
  13. kailash/edge/coordination/raft.py +485 -0
  14. kailash/edge/discovery.py +63 -1
  15. kailash/edge/migration/__init__.py +19 -0
  16. kailash/edge/migration/edge_migrator.py +832 -0
  17. kailash/edge/monitoring/__init__.py +21 -0
  18. kailash/edge/monitoring/edge_monitor.py +736 -0
  19. kailash/edge/prediction/__init__.py +10 -0
  20. kailash/edge/prediction/predictive_warmer.py +591 -0
  21. kailash/edge/resource/__init__.py +102 -0
  22. kailash/edge/resource/cloud_integration.py +796 -0
  23. kailash/edge/resource/cost_optimizer.py +949 -0
  24. kailash/edge/resource/docker_integration.py +919 -0
  25. kailash/edge/resource/kubernetes_integration.py +893 -0
  26. kailash/edge/resource/platform_integration.py +913 -0
  27. kailash/edge/resource/predictive_scaler.py +959 -0
  28. kailash/edge/resource/resource_analyzer.py +824 -0
  29. kailash/edge/resource/resource_pools.py +610 -0
  30. kailash/integrations/dataflow_edge.py +261 -0
  31. kailash/mcp_server/registry_integration.py +1 -1
  32. kailash/monitoring/__init__.py +18 -0
  33. kailash/monitoring/alerts.py +646 -0
  34. kailash/monitoring/metrics.py +677 -0
  35. kailash/nodes/__init__.py +2 -0
  36. kailash/nodes/ai/semantic_memory.py +2 -2
  37. kailash/nodes/base.py +545 -0
  38. kailash/nodes/edge/__init__.py +36 -0
  39. kailash/nodes/edge/base.py +240 -0
  40. kailash/nodes/edge/cloud_node.py +710 -0
  41. kailash/nodes/edge/coordination.py +239 -0
  42. kailash/nodes/edge/docker_node.py +825 -0
  43. kailash/nodes/edge/edge_data.py +582 -0
  44. kailash/nodes/edge/edge_migration_node.py +392 -0
  45. kailash/nodes/edge/edge_monitoring_node.py +421 -0
  46. kailash/nodes/edge/edge_state.py +673 -0
  47. kailash/nodes/edge/edge_warming_node.py +393 -0
  48. kailash/nodes/edge/kubernetes_node.py +652 -0
  49. kailash/nodes/edge/platform_node.py +766 -0
  50. kailash/nodes/edge/resource_analyzer_node.py +378 -0
  51. kailash/nodes/edge/resource_optimizer_node.py +501 -0
  52. kailash/nodes/edge/resource_scaler_node.py +397 -0
  53. kailash/nodes/ports.py +676 -0
  54. kailash/runtime/local.py +344 -1
  55. kailash/runtime/validation/__init__.py +20 -0
  56. kailash/runtime/validation/connection_context.py +119 -0
  57. kailash/runtime/validation/enhanced_error_formatter.py +202 -0
  58. kailash/runtime/validation/error_categorizer.py +164 -0
  59. kailash/runtime/validation/metrics.py +380 -0
  60. kailash/runtime/validation/performance.py +615 -0
  61. kailash/runtime/validation/suggestion_engine.py +212 -0
  62. kailash/testing/fixtures.py +2 -2
  63. kailash/workflow/builder.py +230 -4
  64. kailash/workflow/contracts.py +418 -0
  65. kailash/workflow/edge_infrastructure.py +369 -0
  66. kailash/workflow/migration.py +3 -3
  67. kailash/workflow/type_inference.py +669 -0
  68. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/METADATA +43 -27
  69. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/RECORD +73 -27
  70. kailash/nexus/__init__.py +0 -21
  71. kailash/nexus/cli/__init__.py +0 -5
  72. kailash/nexus/cli/__main__.py +0 -6
  73. kailash/nexus/cli/main.py +0 -176
  74. kailash/nexus/factory.py +0 -413
  75. kailash/nexus/gateway.py +0 -545
  76. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/WHEEL +0 -0
  77. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/entry_points.txt +0 -0
  78. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/licenses/LICENSE +0 -0
  79. {kailash-0.8.4.dist-info → kailash-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,240 @@
1
+ """Base edge-aware node with location awareness and compliance routing."""
2
+
3
+ import asyncio
4
+ from typing import Any, Dict, List, Optional
5
+
6
+ from kailash.edge.compliance import ComplianceRouter, DataClassification
7
+ from kailash.edge.discovery import EdgeDiscovery, EdgeSelectionStrategy
8
+ from kailash.edge.location import EdgeLocation
9
+ from kailash.nodes.base_async import AsyncNode
10
+
11
+
12
+ class EdgeNode(AsyncNode):
13
+ """Base node with edge computing awareness.
14
+
15
+ Extends AsyncNode with:
16
+ - Edge location awareness
17
+ - Automatic edge selection
18
+ - Compliance-aware routing
19
+ - Migration capabilities
20
+ """
21
+
22
+ def __init__(self, **config):
23
+ """Initialize edge-aware node.
24
+
25
+ Args:
26
+ edge_strategy: Edge selection strategy (latency|cost|balanced|compliance)
27
+ preferred_locations: List of preferred edge location names
28
+ compliance_zones: List of required compliance zones (gdpr, ccpa, etc.)
29
+ enable_migration: Whether to enable edge migration capabilities
30
+ **config: Additional node configuration
31
+ """
32
+ self.edge_strategy = EdgeSelectionStrategy(
33
+ config.pop("edge_strategy", "balanced")
34
+ )
35
+ self.preferred_locations = config.pop("preferred_locations", [])
36
+ self.compliance_zones = config.pop("compliance_zones", [])
37
+ self.enable_migration = config.pop("enable_migration", True)
38
+
39
+ # Check for injected infrastructure (from WorkflowBuilder)
40
+ edge_infrastructure = config.pop("_edge_infrastructure", None)
41
+
42
+ if edge_infrastructure:
43
+ # Use shared infrastructure from WorkflowBuilder
44
+ self.edge_discovery = edge_infrastructure.get_discovery()
45
+ self.compliance_router = edge_infrastructure.get_compliance_router()
46
+ self._shared_infrastructure = edge_infrastructure
47
+ else:
48
+ # Standalone mode - create own infrastructure (backward compatibility)
49
+ self.edge_discovery = EdgeDiscovery()
50
+ self.compliance_router = ComplianceRouter()
51
+ self._shared_infrastructure = None
52
+
53
+ self.current_edge: Optional[EdgeLocation] = None
54
+
55
+ super().__init__(**config)
56
+
57
+ async def initialize(self):
58
+ """Initialize edge infrastructure."""
59
+ # No need to call super().initialize() as AsyncNode doesn't have it
60
+
61
+ # Start edge discovery only if not using shared infrastructure
62
+ if not self._shared_infrastructure:
63
+ await self.edge_discovery.start_discovery()
64
+
65
+ # Select initial edge
66
+ self.current_edge = await self._select_edge()
67
+
68
+ if not self.current_edge:
69
+ raise RuntimeError("No suitable edge location found")
70
+
71
+ async def _select_edge(
72
+ self, data: Optional[Dict[str, Any]] = None
73
+ ) -> Optional[EdgeLocation]:
74
+ """Select optimal edge location based on strategy and constraints.
75
+
76
+ Args:
77
+ data: Optional data for compliance classification
78
+
79
+ Returns:
80
+ Selected edge location or None
81
+ """
82
+ # Get all available edges
83
+ edges = self.edge_discovery.get_all_edges()
84
+
85
+ # Filter by preferred locations if specified
86
+ if self.preferred_locations:
87
+ edges = [e for e in edges if e.name in self.preferred_locations]
88
+
89
+ # Filter by compliance if data provided
90
+ if data and self.compliance_zones:
91
+ data_class = self.compliance_router.classify_data(data)
92
+ edges = [
93
+ e
94
+ for e in edges
95
+ if self.compliance_router.is_compliant_location(
96
+ e, data_class, self.compliance_zones
97
+ )
98
+ ]
99
+
100
+ # Apply edge selection strategy
101
+ if not edges:
102
+ return None
103
+
104
+ # If we've already filtered edges, select from the filtered list
105
+ # based on the strategy
106
+ if self.edge_strategy == EdgeSelectionStrategy.LATENCY_OPTIMAL:
107
+ # Select edge with lowest latency
108
+ return min(edges, key=lambda e: e.metrics.latency_p50_ms)
109
+ elif self.edge_strategy == EdgeSelectionStrategy.COST_OPTIMAL:
110
+ # Select edge with lowest cost
111
+ return min(edges, key=lambda e: e.metrics.compute_cost_per_hour)
112
+ elif self.edge_strategy == EdgeSelectionStrategy.COMPLIANCE_FIRST:
113
+ # Already filtered for compliance, pick first
114
+ return edges[0]
115
+ elif self.edge_strategy == EdgeSelectionStrategy.CAPACITY_OPTIMAL:
116
+ # Select edge with most capacity
117
+ return max(
118
+ edges,
119
+ key=lambda e: e.capabilities.cpu_cores
120
+ * (1 - e.metrics.cpu_utilization),
121
+ )
122
+ else: # BALANCED or others
123
+ # Simple balanced selection - pick edge with best combined score
124
+ return min(
125
+ edges,
126
+ key=lambda e: e.metrics.latency_p50_ms
127
+ * e.metrics.compute_cost_per_hour,
128
+ )
129
+
130
+ async def migrate_to_edge(
131
+ self, target_edge: EdgeLocation, state_data: Optional[Dict[str, Any]] = None
132
+ ) -> bool:
133
+ """Migrate this node to a different edge location.
134
+
135
+ Args:
136
+ target_edge: Target edge location
137
+ state_data: Optional state to migrate
138
+
139
+ Returns:
140
+ Success status
141
+ """
142
+ if not self.enable_migration:
143
+ return False
144
+
145
+ try:
146
+ # Prepare for migration
147
+ await self._prepare_migration(target_edge, state_data)
148
+
149
+ # Perform migration
150
+ old_edge = self.current_edge
151
+ self.current_edge = target_edge
152
+
153
+ # Cleanup old edge
154
+ if old_edge:
155
+ await self._cleanup_edge(old_edge)
156
+
157
+ return True
158
+
159
+ except Exception as e:
160
+ self.logger.error(f"Migration failed: {e}")
161
+ return False
162
+
163
+ async def _prepare_migration(
164
+ self, target_edge: EdgeLocation, state_data: Optional[Dict[str, Any]]
165
+ ):
166
+ """Prepare for edge migration."""
167
+ # Override in subclasses for specific preparation
168
+ pass
169
+
170
+ async def _cleanup_edge(self, edge: EdgeLocation):
171
+ """Cleanup after migrating away from an edge."""
172
+ # Override in subclasses for specific cleanup
173
+ pass
174
+
175
+ async def get_edge_metrics(self) -> Dict[str, Any]:
176
+ """Get current edge performance metrics."""
177
+ if not self.current_edge:
178
+ return {}
179
+
180
+ return {
181
+ "edge_name": self.current_edge.name,
182
+ "edge_region": self.current_edge.region,
183
+ "latency_ms": self.current_edge.metrics.latency_p50_ms,
184
+ "cpu_usage": self.current_edge.metrics.cpu_utilization,
185
+ "memory_usage": self.current_edge.metrics.memory_utilization,
186
+ "request_count": self.current_edge.metrics.throughput_rps,
187
+ "error_rate": self.current_edge.metrics.error_rate,
188
+ }
189
+
190
+ def is_compliant_for_data(
191
+ self, data: Dict[str, Any], required_zones: Optional[List[str]] = None
192
+ ) -> bool:
193
+ """Check if current edge is compliant for given data.
194
+
195
+ Args:
196
+ data: Data to check compliance for
197
+ required_zones: Override compliance zones
198
+
199
+ Returns:
200
+ Compliance status
201
+ """
202
+ if not self.current_edge:
203
+ return False
204
+
205
+ zones = required_zones or self.compliance_zones
206
+ if not zones:
207
+ return True
208
+
209
+ data_class = self.compliance_router.classify_data(data)
210
+ return self.compliance_router.is_compliant_location(
211
+ self.current_edge, data_class, zones
212
+ )
213
+
214
+ async def ensure_compliance(
215
+ self, data: Dict[str, Any], required_zones: Optional[List[str]] = None
216
+ ) -> bool:
217
+ """Ensure node is at compliant edge for data.
218
+
219
+ Migrates to compliant edge if necessary.
220
+
221
+ Args:
222
+ data: Data requiring compliance
223
+ required_zones: Override compliance zones
224
+
225
+ Returns:
226
+ Success status
227
+ """
228
+ zones = required_zones or self.compliance_zones
229
+
230
+ # Check current compliance
231
+ if self.is_compliant_for_data(data, zones):
232
+ return True
233
+
234
+ # Find compliant edge
235
+ compliant_edge = await self._select_edge(data)
236
+ if not compliant_edge:
237
+ return False
238
+
239
+ # Migrate to compliant edge
240
+ return await self.migrate_to_edge(compliant_edge)