@plures/praxis 0.2.0
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.
- package/FRAMEWORK.md +420 -0
- package/LICENSE +21 -0
- package/README.md +1310 -0
- package/dist/adapters/cli.d.ts +43 -0
- package/dist/adapters/cli.d.ts.map +1 -0
- package/dist/adapters/cli.js +126 -0
- package/dist/adapters/cli.js.map +1 -0
- package/dist/cli/commands/auth.d.ts +26 -0
- package/dist/cli/commands/auth.d.ts.map +1 -0
- package/dist/cli/commands/auth.js +233 -0
- package/dist/cli/commands/auth.js.map +1 -0
- package/dist/cli/commands/cloud.d.ts +27 -0
- package/dist/cli/commands/cloud.d.ts.map +1 -0
- package/dist/cli/commands/cloud.js +232 -0
- package/dist/cli/commands/cloud.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +25 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +168 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +179 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cloud/auth.d.ts +51 -0
- package/dist/cloud/auth.d.ts.map +1 -0
- package/dist/cloud/auth.js +194 -0
- package/dist/cloud/auth.js.map +1 -0
- package/dist/cloud/billing.d.ts +184 -0
- package/dist/cloud/billing.d.ts.map +1 -0
- package/dist/cloud/billing.js +179 -0
- package/dist/cloud/billing.js.map +1 -0
- package/dist/cloud/client.d.ts +39 -0
- package/dist/cloud/client.d.ts.map +1 -0
- package/dist/cloud/client.js +176 -0
- package/dist/cloud/client.js.map +1 -0
- package/dist/cloud/index.d.ts +44 -0
- package/dist/cloud/index.d.ts.map +1 -0
- package/dist/cloud/index.js +44 -0
- package/dist/cloud/index.js.map +1 -0
- package/dist/cloud/marketplace.d.ts +166 -0
- package/dist/cloud/marketplace.d.ts.map +1 -0
- package/dist/cloud/marketplace.js +159 -0
- package/dist/cloud/marketplace.js.map +1 -0
- package/dist/cloud/provisioning.d.ts +110 -0
- package/dist/cloud/provisioning.d.ts.map +1 -0
- package/dist/cloud/provisioning.js +148 -0
- package/dist/cloud/provisioning.js.map +1 -0
- package/dist/cloud/relay/endpoints.d.ts +62 -0
- package/dist/cloud/relay/endpoints.d.ts.map +1 -0
- package/dist/cloud/relay/endpoints.js +217 -0
- package/dist/cloud/relay/endpoints.js.map +1 -0
- package/dist/cloud/relay/health/index.d.ts +5 -0
- package/dist/cloud/relay/health/index.d.ts.map +1 -0
- package/dist/cloud/relay/health/index.js +9 -0
- package/dist/cloud/relay/health/index.js.map +1 -0
- package/dist/cloud/relay/stats/index.d.ts +5 -0
- package/dist/cloud/relay/stats/index.d.ts.map +1 -0
- package/dist/cloud/relay/stats/index.js +9 -0
- package/dist/cloud/relay/stats/index.js.map +1 -0
- package/dist/cloud/relay/sync/index.d.ts +5 -0
- package/dist/cloud/relay/sync/index.d.ts.map +1 -0
- package/dist/cloud/relay/sync/index.js +9 -0
- package/dist/cloud/relay/sync/index.js.map +1 -0
- package/dist/cloud/relay/usage/index.d.ts +5 -0
- package/dist/cloud/relay/usage/index.d.ts.map +1 -0
- package/dist/cloud/relay/usage/index.js +9 -0
- package/dist/cloud/relay/usage/index.js.map +1 -0
- package/dist/cloud/sponsors.d.ts +81 -0
- package/dist/cloud/sponsors.d.ts.map +1 -0
- package/dist/cloud/sponsors.js +130 -0
- package/dist/cloud/sponsors.js.map +1 -0
- package/dist/cloud/types.d.ts +169 -0
- package/dist/cloud/types.d.ts.map +1 -0
- package/dist/cloud/types.js +7 -0
- package/dist/cloud/types.js.map +1 -0
- package/dist/components/index.d.ts +43 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +17 -0
- package/dist/components/index.js.map +1 -0
- package/dist/core/actors.d.ts +95 -0
- package/dist/core/actors.d.ts.map +1 -0
- package/dist/core/actors.js +158 -0
- package/dist/core/actors.js.map +1 -0
- package/dist/core/component/generator.d.ts +122 -0
- package/dist/core/component/generator.d.ts.map +1 -0
- package/dist/core/component/generator.js +307 -0
- package/dist/core/component/generator.js.map +1 -0
- package/dist/core/engine.d.ts +92 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +199 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/introspection.d.ts +141 -0
- package/dist/core/introspection.d.ts.map +1 -0
- package/dist/core/introspection.js +208 -0
- package/dist/core/introspection.js.map +1 -0
- package/dist/core/logic/generator.d.ts +76 -0
- package/dist/core/logic/generator.d.ts.map +1 -0
- package/dist/core/logic/generator.js +339 -0
- package/dist/core/logic/generator.js.map +1 -0
- package/dist/core/pluresdb/generator.d.ts +58 -0
- package/dist/core/pluresdb/generator.d.ts.map +1 -0
- package/dist/core/pluresdb/generator.js +162 -0
- package/dist/core/pluresdb/generator.js.map +1 -0
- package/dist/core/protocol.d.ts +121 -0
- package/dist/core/protocol.d.ts.map +1 -0
- package/dist/core/protocol.js +46 -0
- package/dist/core/protocol.js.map +1 -0
- package/dist/core/rules.d.ts +120 -0
- package/dist/core/rules.d.ts.map +1 -0
- package/dist/core/rules.js +81 -0
- package/dist/core/rules.js.map +1 -0
- package/dist/core/schema/loader.d.ts +47 -0
- package/dist/core/schema/loader.d.ts.map +1 -0
- package/dist/core/schema/loader.js +189 -0
- package/dist/core/schema/loader.js.map +1 -0
- package/dist/core/schema/normalize.d.ts +72 -0
- package/dist/core/schema/normalize.d.ts.map +1 -0
- package/dist/core/schema/normalize.js +190 -0
- package/dist/core/schema/normalize.js.map +1 -0
- package/dist/core/schema/types.d.ts +370 -0
- package/dist/core/schema/types.d.ts.map +1 -0
- package/dist/core/schema/types.js +161 -0
- package/dist/core/schema/types.js.map +1 -0
- package/dist/dsl/index.d.ts +152 -0
- package/dist/dsl/index.d.ts.map +1 -0
- package/dist/dsl/index.js +132 -0
- package/dist/dsl/index.js.map +1 -0
- package/dist/dsl.d.ts +124 -0
- package/dist/dsl.d.ts.map +1 -0
- package/dist/dsl.js +130 -0
- package/dist/dsl.js.map +1 -0
- package/dist/examples/advanced-todo/index.d.ts +55 -0
- package/dist/examples/advanced-todo/index.d.ts.map +1 -0
- package/dist/examples/advanced-todo/index.js +222 -0
- package/dist/examples/advanced-todo/index.js.map +1 -0
- package/dist/examples/auth-basic/index.d.ts +17 -0
- package/dist/examples/auth-basic/index.d.ts.map +1 -0
- package/dist/examples/auth-basic/index.js +122 -0
- package/dist/examples/auth-basic/index.js.map +1 -0
- package/dist/examples/cart/index.d.ts +19 -0
- package/dist/examples/cart/index.d.ts.map +1 -0
- package/dist/examples/cart/index.js +202 -0
- package/dist/examples/cart/index.js.map +1 -0
- package/dist/examples/hero-ecommerce/index.d.ts +39 -0
- package/dist/examples/hero-ecommerce/index.d.ts.map +1 -0
- package/dist/examples/hero-ecommerce/index.js +506 -0
- package/dist/examples/hero-ecommerce/index.js.map +1 -0
- package/dist/examples/svelte-counter/index.d.ts +31 -0
- package/dist/examples/svelte-counter/index.d.ts.map +1 -0
- package/dist/examples/svelte-counter/index.js +123 -0
- package/dist/examples/svelte-counter/index.js.map +1 -0
- package/dist/flows.d.ts +125 -0
- package/dist/flows.d.ts.map +1 -0
- package/dist/flows.js +160 -0
- package/dist/flows.js.map +1 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -0
- package/dist/integrations/pluresdb.d.ts +56 -0
- package/dist/integrations/pluresdb.d.ts.map +1 -0
- package/dist/integrations/pluresdb.js +46 -0
- package/dist/integrations/pluresdb.js.map +1 -0
- package/dist/integrations/svelte.d.ts +306 -0
- package/dist/integrations/svelte.d.ts.map +1 -0
- package/dist/integrations/svelte.js +447 -0
- package/dist/integrations/svelte.js.map +1 -0
- package/dist/registry.d.ts +94 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +181 -0
- package/dist/registry.js.map +1 -0
- package/dist/runtime/terminal-adapter.d.ts +105 -0
- package/dist/runtime/terminal-adapter.d.ts.map +1 -0
- package/dist/runtime/terminal-adapter.js +113 -0
- package/dist/runtime/terminal-adapter.js.map +1 -0
- package/dist/step.d.ts +34 -0
- package/dist/step.d.ts.map +1 -0
- package/dist/step.js +111 -0
- package/dist/step.js.map +1 -0
- package/dist/types.d.ts +63 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/docs/MONETIZATION.md +394 -0
- package/docs/TERMINAL_NODE.md +588 -0
- package/docs/guides/canvas.md +389 -0
- package/docs/guides/getting-started.md +347 -0
- package/docs/guides/history-state-pattern.md +618 -0
- package/docs/guides/orchestration.md +617 -0
- package/docs/guides/parallel-state-pattern.md +767 -0
- package/docs/guides/svelte-integration.md +691 -0
- package/package.json +96 -0
- package/src/__tests__/actors.test.ts +270 -0
- package/src/__tests__/billing.test.ts +175 -0
- package/src/__tests__/cloud.test.ts +247 -0
- package/src/__tests__/dsl.test.ts +154 -0
- package/src/__tests__/edge-cases.test.ts +475 -0
- package/src/__tests__/engine.test.ts +137 -0
- package/src/__tests__/generators.test.ts +270 -0
- package/src/__tests__/introspection.test.ts +321 -0
- package/src/__tests__/protocol.test.ts +40 -0
- package/src/__tests__/provisioning.test.ts +162 -0
- package/src/__tests__/schema.test.ts +241 -0
- package/src/__tests__/svelte-integration.test.ts +431 -0
- package/src/__tests__/terminal-node.test.ts +352 -0
- package/src/adapters/cli.ts +175 -0
- package/src/cli/commands/auth.ts +271 -0
- package/src/cli/commands/cloud.ts +281 -0
- package/src/cli/commands/generate.ts +225 -0
- package/src/cli/index.ts +190 -0
- package/src/cloud/README.md +383 -0
- package/src/cloud/auth.ts +245 -0
- package/src/cloud/billing.ts +336 -0
- package/src/cloud/client.ts +221 -0
- package/src/cloud/index.ts +121 -0
- package/src/cloud/marketplace.ts +303 -0
- package/src/cloud/provisioning.ts +254 -0
- package/src/cloud/relay/endpoints.ts +307 -0
- package/src/cloud/relay/health/function.json +17 -0
- package/src/cloud/relay/health/index.ts +10 -0
- package/src/cloud/relay/host.json +15 -0
- package/src/cloud/relay/local.settings.json +8 -0
- package/src/cloud/relay/stats/function.json +17 -0
- package/src/cloud/relay/stats/index.ts +10 -0
- package/src/cloud/relay/sync/function.json +17 -0
- package/src/cloud/relay/sync/index.ts +10 -0
- package/src/cloud/relay/usage/function.json +17 -0
- package/src/cloud/relay/usage/index.ts +10 -0
- package/src/cloud/sponsors.ts +213 -0
- package/src/cloud/types.ts +198 -0
- package/src/components/README.md +125 -0
- package/src/components/TerminalNode.svelte +457 -0
- package/src/components/index.ts +46 -0
- package/src/core/actors.ts +205 -0
- package/src/core/component/generator.ts +432 -0
- package/src/core/engine.ts +243 -0
- package/src/core/introspection.ts +329 -0
- package/src/core/logic/generator.ts +420 -0
- package/src/core/pluresdb/generator.ts +229 -0
- package/src/core/protocol.ts +132 -0
- package/src/core/rules.ts +167 -0
- package/src/core/schema/loader.ts +247 -0
- package/src/core/schema/normalize.ts +322 -0
- package/src/core/schema/types.ts +557 -0
- package/src/dsl/index.ts +218 -0
- package/src/dsl.ts +214 -0
- package/src/examples/advanced-todo/App.svelte +506 -0
- package/src/examples/advanced-todo/README.md +371 -0
- package/src/examples/advanced-todo/index.ts +309 -0
- package/src/examples/auth-basic/index.ts +163 -0
- package/src/examples/cart/index.ts +259 -0
- package/src/examples/hero-ecommerce/index.ts +657 -0
- package/src/examples/svelte-counter/index.ts +168 -0
- package/src/flows.ts +268 -0
- package/src/index.ts +154 -0
- package/src/integrations/pluresdb.ts +93 -0
- package/src/integrations/svelte.ts +617 -0
- package/src/registry.ts +223 -0
- package/src/runtime/terminal-adapter.ts +175 -0
- package/src/step.ts +151 -0
- package/src/types.ts +70 -0
- package/templates/basic-app/README.md +147 -0
- package/templates/fullstack-app/README.md +279 -0
|
@@ -0,0 +1,617 @@
|
|
|
1
|
+
# Orchestration with DSC/MCP
|
|
2
|
+
|
|
3
|
+
Praxis provides built-in support for orchestrating distributed systems using Desired State Configuration (DSC) and Model Context Protocol (MCP).
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Praxis orchestration enables:
|
|
8
|
+
- **Multi-Node Coordination**: Manage distributed application instances
|
|
9
|
+
- **State Synchronization**: Keep distributed state consistent
|
|
10
|
+
- **Health Monitoring**: Automatic health checks and recovery
|
|
11
|
+
- **Auto-Scaling**: Dynamic node provisioning
|
|
12
|
+
- **Configuration Management**: Centralized DSC management
|
|
13
|
+
- **Self-Healing**: Automatic failure detection and recovery
|
|
14
|
+
|
|
15
|
+
## Core Concepts
|
|
16
|
+
|
|
17
|
+
### Desired State Configuration (DSC)
|
|
18
|
+
|
|
19
|
+
DSC defines the desired state of your distributed system:
|
|
20
|
+
- Node configurations
|
|
21
|
+
- Service dependencies
|
|
22
|
+
- Resource allocation
|
|
23
|
+
- Network topology
|
|
24
|
+
- Security policies
|
|
25
|
+
|
|
26
|
+
### Model Context Protocol (MCP)
|
|
27
|
+
|
|
28
|
+
MCP enables:
|
|
29
|
+
- Inter-node communication
|
|
30
|
+
- State distribution
|
|
31
|
+
- Event propagation
|
|
32
|
+
- Consensus mechanisms
|
|
33
|
+
|
|
34
|
+
## Getting Started
|
|
35
|
+
|
|
36
|
+
### Enable Orchestration
|
|
37
|
+
|
|
38
|
+
In your schema:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
export const appSchema: PraxisSchema = {
|
|
42
|
+
// ... other schema config
|
|
43
|
+
|
|
44
|
+
orchestration: {
|
|
45
|
+
type: 'dsc',
|
|
46
|
+
nodes: [
|
|
47
|
+
{
|
|
48
|
+
id: 'primary',
|
|
49
|
+
type: 'primary',
|
|
50
|
+
config: {
|
|
51
|
+
host: 'localhost',
|
|
52
|
+
port: 8080,
|
|
53
|
+
role: 'primary',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'replica-1',
|
|
58
|
+
type: 'replica',
|
|
59
|
+
config: {
|
|
60
|
+
host: 'localhost',
|
|
61
|
+
port: 8081,
|
|
62
|
+
role: 'replica',
|
|
63
|
+
replicateFrom: 'primary',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
sync: {
|
|
68
|
+
interval: 5000,
|
|
69
|
+
conflictResolution: 'last-write-wins',
|
|
70
|
+
targets: ['primary', 'replica-1'],
|
|
71
|
+
},
|
|
72
|
+
health: {
|
|
73
|
+
interval: 30000,
|
|
74
|
+
endpoints: ['/health', '/metrics'],
|
|
75
|
+
timeout: 5000,
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Launch Orchestration
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
praxis orchestrate --config src/schemas/app.schema.ts
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Node Types
|
|
88
|
+
|
|
89
|
+
### Primary Node
|
|
90
|
+
|
|
91
|
+
Main coordinator node:
|
|
92
|
+
- Accepts write operations
|
|
93
|
+
- Coordinates state distribution
|
|
94
|
+
- Manages replica health
|
|
95
|
+
- Handles failover
|
|
96
|
+
|
|
97
|
+
### Replica Node
|
|
98
|
+
|
|
99
|
+
Read-replica node:
|
|
100
|
+
- Receives state updates from primary
|
|
101
|
+
- Serves read operations
|
|
102
|
+
- Can become primary on failover
|
|
103
|
+
- Maintains local cache
|
|
104
|
+
|
|
105
|
+
### Worker Node
|
|
106
|
+
|
|
107
|
+
Processing node:
|
|
108
|
+
- Executes background jobs
|
|
109
|
+
- Processes queued tasks
|
|
110
|
+
- Reports status to primary
|
|
111
|
+
- Auto-scales based on load
|
|
112
|
+
|
|
113
|
+
### Gateway Node
|
|
114
|
+
|
|
115
|
+
Entry point node:
|
|
116
|
+
- Load balancing
|
|
117
|
+
- Request routing
|
|
118
|
+
- Authentication
|
|
119
|
+
- Rate limiting
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
### DSC Configuration File
|
|
124
|
+
|
|
125
|
+
Create `orchestration/dsc.config.ts`:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
import type { OrchestrationConfig } from '@plures/praxis/orchestration';
|
|
129
|
+
|
|
130
|
+
export const dscConfig: OrchestrationConfig = {
|
|
131
|
+
// Cluster configuration
|
|
132
|
+
cluster: {
|
|
133
|
+
name: 'my-praxis-cluster',
|
|
134
|
+
region: 'us-east-1',
|
|
135
|
+
nodes: {
|
|
136
|
+
primary: 1,
|
|
137
|
+
replica: 2,
|
|
138
|
+
worker: 3,
|
|
139
|
+
gateway: 1,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
// Node configuration
|
|
144
|
+
nodeDefaults: {
|
|
145
|
+
memory: '512MB',
|
|
146
|
+
cpu: '0.5',
|
|
147
|
+
disk: '10GB',
|
|
148
|
+
network: 'private',
|
|
149
|
+
},
|
|
150
|
+
|
|
151
|
+
// State sync configuration
|
|
152
|
+
sync: {
|
|
153
|
+
protocol: 'websocket',
|
|
154
|
+
interval: 5000,
|
|
155
|
+
batchSize: 100,
|
|
156
|
+
compression: true,
|
|
157
|
+
encryption: true,
|
|
158
|
+
conflictResolution: {
|
|
159
|
+
strategy: 'last-write-wins',
|
|
160
|
+
customResolver: './resolvers/custom.ts',
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
|
|
164
|
+
// Health monitoring
|
|
165
|
+
health: {
|
|
166
|
+
checkInterval: 30000,
|
|
167
|
+
timeout: 5000,
|
|
168
|
+
retries: 3,
|
|
169
|
+
endpoints: {
|
|
170
|
+
liveness: '/health/live',
|
|
171
|
+
readiness: '/health/ready',
|
|
172
|
+
metrics: '/metrics',
|
|
173
|
+
},
|
|
174
|
+
alerts: {
|
|
175
|
+
email: ['ops@example.com'],
|
|
176
|
+
slack: 'https://hooks.slack.com/...',
|
|
177
|
+
},
|
|
178
|
+
},
|
|
179
|
+
|
|
180
|
+
// Auto-scaling
|
|
181
|
+
scaling: {
|
|
182
|
+
enabled: true,
|
|
183
|
+
metrics: ['cpu', 'memory', 'requests'],
|
|
184
|
+
rules: [
|
|
185
|
+
{
|
|
186
|
+
metric: 'cpu',
|
|
187
|
+
threshold: 80,
|
|
188
|
+
action: 'scale-up',
|
|
189
|
+
cooldown: 300000,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
metric: 'requests',
|
|
193
|
+
threshold: 1000,
|
|
194
|
+
action: 'scale-up',
|
|
195
|
+
cooldown: 300000,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
limits: {
|
|
199
|
+
minNodes: 2,
|
|
200
|
+
maxNodes: 10,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
// Service discovery
|
|
205
|
+
discovery: {
|
|
206
|
+
enabled: true,
|
|
207
|
+
protocol: 'consul',
|
|
208
|
+
ttl: 60000,
|
|
209
|
+
tags: ['praxis', 'production'],
|
|
210
|
+
},
|
|
211
|
+
|
|
212
|
+
// Load balancing
|
|
213
|
+
loadBalancing: {
|
|
214
|
+
strategy: 'round-robin', // 'round-robin' | 'least-conn' | 'ip-hash'
|
|
215
|
+
stickySession: true,
|
|
216
|
+
healthCheck: true,
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## State Synchronization
|
|
222
|
+
|
|
223
|
+
### Sync Strategies
|
|
224
|
+
|
|
225
|
+
**Last-Write-Wins**:
|
|
226
|
+
```typescript
|
|
227
|
+
conflictResolution: 'last-write-wins'
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Merge Strategy**:
|
|
231
|
+
```typescript
|
|
232
|
+
conflictResolution: 'merge'
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
**Custom Resolver**:
|
|
236
|
+
```typescript
|
|
237
|
+
conflictResolution: {
|
|
238
|
+
strategy: 'custom',
|
|
239
|
+
resolver: (local, remote) => {
|
|
240
|
+
// Custom merge logic
|
|
241
|
+
return merged;
|
|
242
|
+
},
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Event Distribution
|
|
247
|
+
|
|
248
|
+
Events are automatically distributed to all nodes:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
// Node A dispatches event
|
|
252
|
+
engine.step([LoginEvent.create({ userId: 'user123' })]);
|
|
253
|
+
|
|
254
|
+
// Event propagates to all nodes via MCP
|
|
255
|
+
// Each node applies the event to its local state
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
### State Queries
|
|
259
|
+
|
|
260
|
+
Query distributed state:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// Query primary node
|
|
264
|
+
const state = await orchestrator.getState('primary');
|
|
265
|
+
|
|
266
|
+
// Query all nodes
|
|
267
|
+
const allStates = await orchestrator.getAllStates();
|
|
268
|
+
|
|
269
|
+
// Query with filter
|
|
270
|
+
const activeNodes = await orchestrator.getStates({
|
|
271
|
+
role: 'replica',
|
|
272
|
+
status: 'active',
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Health Monitoring
|
|
277
|
+
|
|
278
|
+
### Health Checks
|
|
279
|
+
|
|
280
|
+
Define health check endpoints:
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
// src/orchestration/health.ts
|
|
284
|
+
export const healthChecks = {
|
|
285
|
+
liveness: async () => {
|
|
286
|
+
// Check if node is alive
|
|
287
|
+
return { status: 'ok' };
|
|
288
|
+
},
|
|
289
|
+
|
|
290
|
+
readiness: async () => {
|
|
291
|
+
// Check if node is ready to serve requests
|
|
292
|
+
const dbReady = await checkDatabase();
|
|
293
|
+
const cacheReady = await checkCache();
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
status: dbReady && cacheReady ? 'ok' : 'not-ready',
|
|
297
|
+
details: { database: dbReady, cache: cacheReady },
|
|
298
|
+
};
|
|
299
|
+
},
|
|
300
|
+
|
|
301
|
+
metrics: async () => {
|
|
302
|
+
// Return metrics
|
|
303
|
+
return {
|
|
304
|
+
cpu: process.cpuUsage(),
|
|
305
|
+
memory: process.memoryUsage(),
|
|
306
|
+
requests: requestCounter.count,
|
|
307
|
+
};
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Failure Detection
|
|
313
|
+
|
|
314
|
+
Automatic failure detection:
|
|
315
|
+
- Heartbeat monitoring
|
|
316
|
+
- Health check failures
|
|
317
|
+
- Network partition detection
|
|
318
|
+
- Resource exhaustion alerts
|
|
319
|
+
|
|
320
|
+
### Recovery Actions
|
|
321
|
+
|
|
322
|
+
Configured recovery actions:
|
|
323
|
+
- **Restart**: Restart failed node
|
|
324
|
+
- **Failover**: Promote replica to primary
|
|
325
|
+
- **Scale**: Add new nodes
|
|
326
|
+
- **Alert**: Notify operations team
|
|
327
|
+
|
|
328
|
+
## Auto-Scaling
|
|
329
|
+
|
|
330
|
+
### Scaling Rules
|
|
331
|
+
|
|
332
|
+
Define when to scale:
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
scaling: {
|
|
336
|
+
rules: [
|
|
337
|
+
{
|
|
338
|
+
name: 'high-cpu',
|
|
339
|
+
metric: 'cpu',
|
|
340
|
+
threshold: 80,
|
|
341
|
+
duration: 60000, // sustained for 1 minute
|
|
342
|
+
action: 'scale-up',
|
|
343
|
+
amount: 1, // add 1 node
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
name: 'low-load',
|
|
347
|
+
metric: 'requests',
|
|
348
|
+
threshold: 100,
|
|
349
|
+
duration: 300000, // sustained for 5 minutes
|
|
350
|
+
action: 'scale-down',
|
|
351
|
+
amount: 1, // remove 1 node
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Manual Scaling
|
|
358
|
+
|
|
359
|
+
Scale via CLI:
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
# Scale up
|
|
363
|
+
praxis orchestrate scale up --nodes 2
|
|
364
|
+
|
|
365
|
+
# Scale down
|
|
366
|
+
praxis orchestrate scale down --nodes 1
|
|
367
|
+
|
|
368
|
+
# Set exact count
|
|
369
|
+
praxis orchestrate scale set --nodes 5
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Example: Self-Healing System
|
|
373
|
+
|
|
374
|
+
### Configuration
|
|
375
|
+
|
|
376
|
+
```typescript
|
|
377
|
+
const selfHealingConfig = {
|
|
378
|
+
health: {
|
|
379
|
+
checkInterval: 10000,
|
|
380
|
+
failureThreshold: 3,
|
|
381
|
+
recoveryActions: [
|
|
382
|
+
{
|
|
383
|
+
condition: 'node-unhealthy',
|
|
384
|
+
action: 'restart',
|
|
385
|
+
maxRetries: 3,
|
|
386
|
+
},
|
|
387
|
+
{
|
|
388
|
+
condition: 'restart-failed',
|
|
389
|
+
action: 'failover',
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
condition: 'primary-failed',
|
|
393
|
+
action: 'promote-replica',
|
|
394
|
+
targetRole: 'primary',
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
},
|
|
398
|
+
};
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Monitoring
|
|
402
|
+
|
|
403
|
+
```bash
|
|
404
|
+
# Monitor cluster status
|
|
405
|
+
praxis orchestrate status
|
|
406
|
+
|
|
407
|
+
# Watch health in real-time
|
|
408
|
+
praxis orchestrate health --watch
|
|
409
|
+
|
|
410
|
+
# View node details
|
|
411
|
+
praxis orchestrate node info primary
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## Integration with Praxis Logic
|
|
415
|
+
|
|
416
|
+
### Distributed Events
|
|
417
|
+
|
|
418
|
+
Events propagate across nodes:
|
|
419
|
+
|
|
420
|
+
```typescript
|
|
421
|
+
// Define distributed event
|
|
422
|
+
const UserLoginEvent = defineEvent<'USER_LOGIN', { userId: string }>(
|
|
423
|
+
'USER_LOGIN'
|
|
424
|
+
);
|
|
425
|
+
|
|
426
|
+
// Dispatch on any node
|
|
427
|
+
engine.step([UserLoginEvent.create({ userId: 'user123' })]);
|
|
428
|
+
|
|
429
|
+
// Event automatically propagates to all nodes
|
|
430
|
+
// Each node processes the event with its local logic
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### Distributed Facts
|
|
434
|
+
|
|
435
|
+
Facts are synchronized across nodes:
|
|
436
|
+
|
|
437
|
+
```typescript
|
|
438
|
+
// Primary node creates fact
|
|
439
|
+
const fact = UserLoggedIn.create({ userId: 'user123', nodeId: 'primary' });
|
|
440
|
+
|
|
441
|
+
// Fact syncs to all replicas
|
|
442
|
+
// Replicas can query the fact locally
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### Distributed Constraints
|
|
446
|
+
|
|
447
|
+
Constraints can be enforced cluster-wide:
|
|
448
|
+
|
|
449
|
+
```typescript
|
|
450
|
+
const maxUsersConstraint = defineConstraint({
|
|
451
|
+
id: 'max-users-global',
|
|
452
|
+
description: 'Maximum 10000 active users cluster-wide',
|
|
453
|
+
impl: async (state) => {
|
|
454
|
+
// Query all nodes for user count
|
|
455
|
+
const totalUsers = await orchestrator.aggregateMetric('active-users');
|
|
456
|
+
return totalUsers <= 10000;
|
|
457
|
+
},
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
## Production Deployment
|
|
462
|
+
|
|
463
|
+
### Container Deployment
|
|
464
|
+
|
|
465
|
+
```dockerfile
|
|
466
|
+
# Dockerfile
|
|
467
|
+
FROM node:18-alpine
|
|
468
|
+
|
|
469
|
+
WORKDIR /app
|
|
470
|
+
COPY package*.json ./
|
|
471
|
+
RUN npm ci --production
|
|
472
|
+
|
|
473
|
+
COPY dist ./dist
|
|
474
|
+
COPY orchestration ./orchestration
|
|
475
|
+
|
|
476
|
+
CMD ["praxis", "orchestrate", "--config", "orchestration/dsc.config.ts"]
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Kubernetes Deployment
|
|
480
|
+
|
|
481
|
+
```yaml
|
|
482
|
+
# k8s/deployment.yaml
|
|
483
|
+
apiVersion: apps/v1
|
|
484
|
+
kind: Deployment
|
|
485
|
+
metadata:
|
|
486
|
+
name: praxis-app
|
|
487
|
+
spec:
|
|
488
|
+
replicas: 3
|
|
489
|
+
selector:
|
|
490
|
+
matchLabels:
|
|
491
|
+
app: praxis-app
|
|
492
|
+
template:
|
|
493
|
+
metadata:
|
|
494
|
+
labels:
|
|
495
|
+
app: praxis-app
|
|
496
|
+
spec:
|
|
497
|
+
containers:
|
|
498
|
+
- name: praxis
|
|
499
|
+
image: my-praxis-app:latest
|
|
500
|
+
ports:
|
|
501
|
+
- containerPort: 8080
|
|
502
|
+
env:
|
|
503
|
+
- name: NODE_TYPE
|
|
504
|
+
value: "replica"
|
|
505
|
+
- name: PRIMARY_HOST
|
|
506
|
+
value: "praxis-primary"
|
|
507
|
+
livenessProbe:
|
|
508
|
+
httpGet:
|
|
509
|
+
path: /health/live
|
|
510
|
+
port: 8080
|
|
511
|
+
readinessProbe:
|
|
512
|
+
httpGet:
|
|
513
|
+
path: /health/ready
|
|
514
|
+
port: 8080
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
## Monitoring & Observability
|
|
518
|
+
|
|
519
|
+
### Metrics
|
|
520
|
+
|
|
521
|
+
Collect cluster metrics:
|
|
522
|
+
- Request rate per node
|
|
523
|
+
- State sync latency
|
|
524
|
+
- Health check status
|
|
525
|
+
- Resource usage
|
|
526
|
+
- Event throughput
|
|
527
|
+
|
|
528
|
+
### Logging
|
|
529
|
+
|
|
530
|
+
Centralized logging:
|
|
531
|
+
|
|
532
|
+
```typescript
|
|
533
|
+
orchestration: {
|
|
534
|
+
logging: {
|
|
535
|
+
level: 'info',
|
|
536
|
+
format: 'json',
|
|
537
|
+
outputs: [
|
|
538
|
+
{ type: 'console' },
|
|
539
|
+
{ type: 'file', path: '/var/log/praxis.log' },
|
|
540
|
+
{ type: 'elasticsearch', url: 'http://elastic:9200' },
|
|
541
|
+
],
|
|
542
|
+
},
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### Tracing
|
|
547
|
+
|
|
548
|
+
Distributed tracing with OpenTelemetry:
|
|
549
|
+
|
|
550
|
+
```typescript
|
|
551
|
+
orchestration: {
|
|
552
|
+
tracing: {
|
|
553
|
+
enabled: true,
|
|
554
|
+
serviceName: 'praxis-app',
|
|
555
|
+
exporter: 'jaeger',
|
|
556
|
+
endpoint: 'http://jaeger:14268/api/traces',
|
|
557
|
+
},
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
## Troubleshooting
|
|
562
|
+
|
|
563
|
+
### Split Brain
|
|
564
|
+
|
|
565
|
+
Detect and resolve split brain:
|
|
566
|
+
```bash
|
|
567
|
+
praxis orchestrate diagnose split-brain
|
|
568
|
+
praxis orchestrate resolve split-brain --strategy quorum
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
### Network Partition
|
|
572
|
+
|
|
573
|
+
Handle network partitions:
|
|
574
|
+
```typescript
|
|
575
|
+
sync: {
|
|
576
|
+
partitionTolerance: {
|
|
577
|
+
strategy: 'availability', // or 'consistency'
|
|
578
|
+
timeout: 30000,
|
|
579
|
+
},
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### State Divergence
|
|
584
|
+
|
|
585
|
+
Reconcile diverged state:
|
|
586
|
+
```bash
|
|
587
|
+
praxis orchestrate reconcile --force
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
## Best Practices
|
|
591
|
+
|
|
592
|
+
1. **Start Small**: Begin with 2-3 nodes
|
|
593
|
+
2. **Monitor Everything**: Enable comprehensive monitoring
|
|
594
|
+
3. **Test Failures**: Practice failover scenarios
|
|
595
|
+
4. **Document Topology**: Keep network diagrams updated
|
|
596
|
+
5. **Automate Recovery**: Configure self-healing
|
|
597
|
+
6. **Version Carefully**: Coordinate version upgrades
|
|
598
|
+
7. **Backup State**: Regular state snapshots
|
|
599
|
+
8. **Secure Communication**: Use TLS for node communication
|
|
600
|
+
|
|
601
|
+
## Next Steps
|
|
602
|
+
|
|
603
|
+
- Review orchestration examples
|
|
604
|
+
- Test failover scenarios
|
|
605
|
+
- Configure monitoring
|
|
606
|
+
- Set up alerts
|
|
607
|
+
- Plan capacity
|
|
608
|
+
- Document runbooks
|
|
609
|
+
|
|
610
|
+
## Resources
|
|
611
|
+
|
|
612
|
+
- [Orchestration Examples](../../examples/orchestration/)
|
|
613
|
+
- [DSC Reference](../api/dsc.md)
|
|
614
|
+
- [MCP Protocol](../api/mcp.md)
|
|
615
|
+
- [Production Guide](./production.md)
|
|
616
|
+
|
|
617
|
+
Build resilient, distributed applications with Praxis orchestration! 🌐
|