kailash 0.8.3__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.
- kailash/__init__.py +1 -7
- kailash/cli/__init__.py +11 -1
- kailash/cli/validation_audit.py +570 -0
- kailash/core/actors/supervisor.py +1 -1
- kailash/core/resilience/circuit_breaker.py +71 -1
- kailash/core/resilience/health_monitor.py +172 -0
- kailash/edge/compliance.py +33 -0
- kailash/edge/consistency.py +609 -0
- kailash/edge/coordination/__init__.py +30 -0
- kailash/edge/coordination/global_ordering.py +355 -0
- kailash/edge/coordination/leader_election.py +217 -0
- kailash/edge/coordination/partition_detector.py +296 -0
- kailash/edge/coordination/raft.py +485 -0
- kailash/edge/discovery.py +63 -1
- kailash/edge/migration/__init__.py +19 -0
- kailash/edge/migration/edge_migrator.py +832 -0
- kailash/edge/monitoring/__init__.py +21 -0
- kailash/edge/monitoring/edge_monitor.py +736 -0
- kailash/edge/prediction/__init__.py +10 -0
- kailash/edge/prediction/predictive_warmer.py +591 -0
- kailash/edge/resource/__init__.py +102 -0
- kailash/edge/resource/cloud_integration.py +796 -0
- kailash/edge/resource/cost_optimizer.py +949 -0
- kailash/edge/resource/docker_integration.py +919 -0
- kailash/edge/resource/kubernetes_integration.py +893 -0
- kailash/edge/resource/platform_integration.py +913 -0
- kailash/edge/resource/predictive_scaler.py +959 -0
- kailash/edge/resource/resource_analyzer.py +824 -0
- kailash/edge/resource/resource_pools.py +610 -0
- kailash/integrations/dataflow_edge.py +261 -0
- kailash/mcp_server/registry_integration.py +1 -1
- kailash/monitoring/__init__.py +18 -0
- kailash/monitoring/alerts.py +646 -0
- kailash/monitoring/metrics.py +677 -0
- kailash/nodes/__init__.py +2 -0
- kailash/nodes/ai/__init__.py +17 -0
- kailash/nodes/ai/a2a.py +1914 -43
- kailash/nodes/ai/a2a_backup.py +1807 -0
- kailash/nodes/ai/hybrid_search.py +972 -0
- kailash/nodes/ai/semantic_memory.py +558 -0
- kailash/nodes/ai/streaming_analytics.py +947 -0
- kailash/nodes/base.py +545 -0
- kailash/nodes/edge/__init__.py +36 -0
- kailash/nodes/edge/base.py +240 -0
- kailash/nodes/edge/cloud_node.py +710 -0
- kailash/nodes/edge/coordination.py +239 -0
- kailash/nodes/edge/docker_node.py +825 -0
- kailash/nodes/edge/edge_data.py +582 -0
- kailash/nodes/edge/edge_migration_node.py +392 -0
- kailash/nodes/edge/edge_monitoring_node.py +421 -0
- kailash/nodes/edge/edge_state.py +673 -0
- kailash/nodes/edge/edge_warming_node.py +393 -0
- kailash/nodes/edge/kubernetes_node.py +652 -0
- kailash/nodes/edge/platform_node.py +766 -0
- kailash/nodes/edge/resource_analyzer_node.py +378 -0
- kailash/nodes/edge/resource_optimizer_node.py +501 -0
- kailash/nodes/edge/resource_scaler_node.py +397 -0
- kailash/nodes/ports.py +676 -0
- kailash/runtime/local.py +344 -1
- kailash/runtime/validation/__init__.py +20 -0
- kailash/runtime/validation/connection_context.py +119 -0
- kailash/runtime/validation/enhanced_error_formatter.py +202 -0
- kailash/runtime/validation/error_categorizer.py +164 -0
- kailash/runtime/validation/metrics.py +380 -0
- kailash/runtime/validation/performance.py +615 -0
- kailash/runtime/validation/suggestion_engine.py +212 -0
- kailash/testing/fixtures.py +2 -2
- kailash/workflow/builder.py +234 -8
- kailash/workflow/contracts.py +418 -0
- kailash/workflow/edge_infrastructure.py +369 -0
- kailash/workflow/migration.py +3 -3
- kailash/workflow/type_inference.py +669 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/METADATA +44 -27
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/RECORD +78 -28
- kailash/nexus/__init__.py +0 -21
- kailash/nexus/cli/__init__.py +0 -5
- kailash/nexus/cli/__main__.py +0 -6
- kailash/nexus/cli/main.py +0 -176
- kailash/nexus/factory.py +0 -413
- kailash/nexus/gateway.py +0 -545
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/WHEEL +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/entry_points.txt +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.8.3.dist-info → kailash-0.8.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,239 @@
|
|
1
|
+
"""Edge coordination node for distributed consensus operations."""
|
2
|
+
|
3
|
+
import asyncio
|
4
|
+
from datetime import datetime
|
5
|
+
from typing import Any, Dict, List, Optional
|
6
|
+
|
7
|
+
from kailash.edge.coordination import (
|
8
|
+
EdgeLeaderElection,
|
9
|
+
GlobalOrderingService,
|
10
|
+
RaftNode,
|
11
|
+
RaftState,
|
12
|
+
)
|
13
|
+
from kailash.nodes.base import NodeParameter, register_node
|
14
|
+
from kailash.nodes.base_async import AsyncNode
|
15
|
+
|
16
|
+
|
17
|
+
@register_node()
|
18
|
+
class EdgeCoordinationNode(AsyncNode):
|
19
|
+
"""Node providing distributed coordination operations for edge computing.
|
20
|
+
|
21
|
+
This node enables:
|
22
|
+
- Leader election among edge nodes
|
23
|
+
- Distributed consensus via Raft
|
24
|
+
- Global event ordering
|
25
|
+
- Split-brain prevention
|
26
|
+
|
27
|
+
Example:
|
28
|
+
```python
|
29
|
+
# Elect leader for coordination group
|
30
|
+
workflow.add_node("EdgeCoordinationNode", "coordinator", {
|
31
|
+
"operation": "elect_leader",
|
32
|
+
"coordination_group": "cache_cluster"
|
33
|
+
})
|
34
|
+
|
35
|
+
# Propose change through consensus
|
36
|
+
workflow.add_node("EdgeCoordinationNode", "propose", {
|
37
|
+
"operation": "propose",
|
38
|
+
"coordination_group": "cache_cluster",
|
39
|
+
"proposal": {"action": "invalidate", "keys": ["user:*"]}
|
40
|
+
})
|
41
|
+
```
|
42
|
+
"""
|
43
|
+
|
44
|
+
def get_parameters(self) -> Dict[str, NodeParameter]:
|
45
|
+
"""Get node parameters."""
|
46
|
+
return {
|
47
|
+
"operation": NodeParameter(
|
48
|
+
name="operation",
|
49
|
+
type=str,
|
50
|
+
required=True,
|
51
|
+
description="Operation to perform: elect_leader|get_leader|propose|global_order",
|
52
|
+
),
|
53
|
+
"coordination_group": NodeParameter(
|
54
|
+
name="coordination_group",
|
55
|
+
type=str,
|
56
|
+
default="default",
|
57
|
+
required=False,
|
58
|
+
description="Coordination group name for isolation",
|
59
|
+
),
|
60
|
+
"node_id": NodeParameter(
|
61
|
+
name="node_id",
|
62
|
+
type=str,
|
63
|
+
required=False,
|
64
|
+
description="Unique node ID (auto-generated if not provided)",
|
65
|
+
),
|
66
|
+
"peers": NodeParameter(
|
67
|
+
name="peers",
|
68
|
+
type=list,
|
69
|
+
required=False,
|
70
|
+
description="List of peer node IDs",
|
71
|
+
),
|
72
|
+
"proposal": NodeParameter(
|
73
|
+
name="proposal",
|
74
|
+
type=dict,
|
75
|
+
required=False,
|
76
|
+
description="Proposal data for consensus",
|
77
|
+
),
|
78
|
+
"events": NodeParameter(
|
79
|
+
name="events",
|
80
|
+
type=list,
|
81
|
+
required=False,
|
82
|
+
description="Events to order globally",
|
83
|
+
),
|
84
|
+
}
|
85
|
+
|
86
|
+
# Class-level coordination groups
|
87
|
+
_coordination_groups: Dict[str, Dict[str, Any]] = {}
|
88
|
+
|
89
|
+
def __init__(self, **config):
|
90
|
+
"""Initialize coordination node."""
|
91
|
+
super().__init__(**config)
|
92
|
+
|
93
|
+
self.coordination_group = config.get("coordination_group", "default")
|
94
|
+
self.node_id = config.get("node_id", f"node_{id(self)}")
|
95
|
+
self.peers = config.get("peers", [])
|
96
|
+
|
97
|
+
# Get or create coordination group
|
98
|
+
if self.coordination_group not in self._coordination_groups:
|
99
|
+
self._coordination_groups[self.coordination_group] = {
|
100
|
+
"raft_nodes": {},
|
101
|
+
"leader_election": None,
|
102
|
+
"ordering_service": None,
|
103
|
+
}
|
104
|
+
|
105
|
+
self.group = self._coordination_groups[self.coordination_group]
|
106
|
+
|
107
|
+
# Initialize services lazily
|
108
|
+
self.raft_node: Optional[RaftNode] = None
|
109
|
+
self.leader_election: Optional[EdgeLeaderElection] = None
|
110
|
+
self.ordering_service: Optional[GlobalOrderingService] = None
|
111
|
+
|
112
|
+
# Metrics
|
113
|
+
self.metrics = {
|
114
|
+
"elections_started": 0,
|
115
|
+
"consensus_proposals": 0,
|
116
|
+
"ordering_requests": 0,
|
117
|
+
"errors": 0,
|
118
|
+
}
|
119
|
+
|
120
|
+
async def _ensure_services(self):
|
121
|
+
"""Ensure required services are initialized."""
|
122
|
+
# Initialize Raft node if needed
|
123
|
+
if self.raft_node is None:
|
124
|
+
if self.node_id in self.group["raft_nodes"]:
|
125
|
+
self.raft_node = self.group["raft_nodes"][self.node_id]
|
126
|
+
else:
|
127
|
+
self.raft_node = RaftNode(self.node_id, self.peers or [])
|
128
|
+
self.group["raft_nodes"][self.node_id] = self.raft_node
|
129
|
+
await self.raft_node.start()
|
130
|
+
|
131
|
+
# Initialize leader election service
|
132
|
+
if self.leader_election is None:
|
133
|
+
if self.group["leader_election"] is None:
|
134
|
+
self.group["leader_election"] = EdgeLeaderElection(
|
135
|
+
self.group["raft_nodes"]
|
136
|
+
)
|
137
|
+
self.leader_election = self.group["leader_election"]
|
138
|
+
|
139
|
+
# Initialize ordering service
|
140
|
+
if self.ordering_service is None:
|
141
|
+
if self.group["ordering_service"] is None:
|
142
|
+
self.group["ordering_service"] = GlobalOrderingService(self.node_id)
|
143
|
+
self.ordering_service = self.group["ordering_service"]
|
144
|
+
|
145
|
+
async def async_run(self, **kwargs) -> Dict[str, Any]:
|
146
|
+
"""Execute coordination operation."""
|
147
|
+
await self._ensure_services()
|
148
|
+
|
149
|
+
operation = kwargs.get("operation")
|
150
|
+
|
151
|
+
try:
|
152
|
+
if operation == "elect_leader":
|
153
|
+
return await self._handle_elect_leader(kwargs)
|
154
|
+
elif operation == "get_leader":
|
155
|
+
return await self._handle_get_leader(kwargs)
|
156
|
+
elif operation == "propose":
|
157
|
+
return await self._handle_propose(kwargs)
|
158
|
+
elif operation == "global_order":
|
159
|
+
return await self._handle_global_order(kwargs)
|
160
|
+
else:
|
161
|
+
self.metrics["errors"] += 1
|
162
|
+
return {"success": False, "error": f"Unknown operation: {operation}"}
|
163
|
+
except Exception as e:
|
164
|
+
self.logger.error(f"Coordination operation failed: {e}")
|
165
|
+
self.metrics["errors"] += 1
|
166
|
+
return {"success": False, "error": str(e)}
|
167
|
+
|
168
|
+
async def _handle_elect_leader(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
169
|
+
"""Handle leader election operation."""
|
170
|
+
self.metrics["elections_started"] += 1
|
171
|
+
|
172
|
+
result = await self.leader_election.start_election()
|
173
|
+
|
174
|
+
return {
|
175
|
+
"success": True,
|
176
|
+
"leader": result["leader"],
|
177
|
+
"term": result["term"],
|
178
|
+
"timestamp": datetime.now().isoformat(),
|
179
|
+
}
|
180
|
+
|
181
|
+
async def _handle_get_leader(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
182
|
+
"""Handle get current leader operation."""
|
183
|
+
leader_info = self.leader_election.get_current_leader()
|
184
|
+
|
185
|
+
return {
|
186
|
+
"success": True,
|
187
|
+
"leader": leader_info["leader"],
|
188
|
+
"term": leader_info["term"],
|
189
|
+
"stable": leader_info["stable"],
|
190
|
+
"timestamp": datetime.now().isoformat(),
|
191
|
+
}
|
192
|
+
|
193
|
+
async def _handle_propose(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
194
|
+
"""Handle consensus proposal operation."""
|
195
|
+
proposal = params.get("proposal")
|
196
|
+
if not proposal:
|
197
|
+
return {
|
198
|
+
"success": False,
|
199
|
+
"error": "Proposal required for propose operation",
|
200
|
+
}
|
201
|
+
|
202
|
+
# Check if we have a leader
|
203
|
+
leader_info = self.leader_election.get_current_leader()
|
204
|
+
if not leader_info["leader"]:
|
205
|
+
return {
|
206
|
+
"success": False,
|
207
|
+
"error": "No leader elected - cannot process proposal",
|
208
|
+
}
|
209
|
+
|
210
|
+
self.metrics["consensus_proposals"] += 1
|
211
|
+
|
212
|
+
# Submit proposal through Raft
|
213
|
+
result = await self.raft_node.propose(proposal)
|
214
|
+
|
215
|
+
return {
|
216
|
+
"success": result["success"],
|
217
|
+
"accepted": result["success"],
|
218
|
+
"log_index": result.get("index"),
|
219
|
+
"term": result.get("term"),
|
220
|
+
"error": result.get("error"),
|
221
|
+
"timestamp": datetime.now().isoformat(),
|
222
|
+
}
|
223
|
+
|
224
|
+
async def _handle_global_order(self, params: Dict[str, Any]) -> Dict[str, Any]:
|
225
|
+
"""Handle global ordering operation."""
|
226
|
+
events = params.get("events", [])
|
227
|
+
|
228
|
+
self.metrics["ordering_requests"] += 1
|
229
|
+
|
230
|
+
# Order events
|
231
|
+
result = await self.ordering_service.order_events(events)
|
232
|
+
|
233
|
+
return {
|
234
|
+
"success": True,
|
235
|
+
"ordered_events": result["ordered_events"],
|
236
|
+
"logical_clock": result["logical_clock"],
|
237
|
+
"causal_dependencies": result.get("causal_dependencies", {}),
|
238
|
+
"timestamp": datetime.now().isoformat(),
|
239
|
+
}
|