thefinalboss commited on
Commit
b2a12c6
·
verified ·
1 Parent(s): 0c9382c

Add AICL example: 16_microservices.aicl

Browse files
data/aicl/examples/16_microservices.aicl ADDED
@@ -0,0 +1,368 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AICL Example: Microservices Architecture
2
+ # Implements a production-grade microservices system with service discovery, API gateway,
3
+ # circuit breaker, saga pattern for distributed transactions, and distributed tracing.
4
+
5
+ # Level 1: Architecture
6
+ Goal: Build a resilient microservices architecture supporting independent service deployment,
7
+ cross-service communication, fault isolation, distributed transaction coordination via saga,
8
+ and full observability through distributed tracing.
9
+
10
+ Constraint: No service may directly reference another service's internal data store.
11
+ Constraint: All inter-service communication must traverse the API gateway.
12
+ Constraint: Each service must be independently deployable and scalable.
13
+ Constraint: Latency for synchronous calls must remain below 200ms p99.
14
+ Constraint: Saga transactions must complete within 30 seconds or compensate.
15
+
16
+ Risk: Service discovery failure leaves orphaned instances
17
+ Recovery: Fallback to static registry with heartbeat-based health checks and manual override
18
+
19
+ Risk: Circuit breaker cascade causes system-wide outage
20
+ Recovery: Bulkhead isolation per service with independent breaker pools and graceful degradation
21
+
22
+ Risk: Saga participant crash mid-transaction leaves partial state
23
+ Recovery: Saga orchestrator retries with exponential backoff; compensating transactions for unrecoverable failures
24
+
25
+ Risk: API gateway becomes single point of failure
26
+ Recovery: Deploy gateway replicas across availability zones with leader election and failover routing
27
+
28
+ Risk: Distributed trace context lost across async boundaries
29
+ Recovery: Inject trace context into message headers; background reconciler repairs broken traces
30
+
31
+ Risk: Network partition causes split-brain service registry
32
+ Recovery: Quorum-based registration with majority-wins consensus and stale-entry eviction
33
+
34
+ Layer: Infrastructure
35
+ SubLayer: ServiceDiscovery
36
+ SubLayer: APIGateway
37
+ SubLayer: MessageBus
38
+ Layer: Services
39
+ SubLayer: OrderService
40
+ SubLayer: PaymentService
41
+ SubLayer: InventoryService
42
+ SubLayer: NotificationService
43
+ Layer: Observability
44
+ SubLayer: DistributedTracing
45
+ SubLayer: MetricsAggregator
46
+ SubLayer: LogCollector
47
+
48
+ Validation: Service registry heartbeat must arrive every 5 seconds
49
+ Validation: API gateway route table must match deployed service count
50
+ Validation: Circuit breaker open duration must not exceed 60 seconds
51
+ Validation: Saga transaction must have a defined compensating action for every step
52
+ Validation: Distributed trace spans must propagate correlation IDs across all hops
53
+ Validation: Service health endpoint must respond within 500ms
54
+
55
+ # Level 2: Entities
56
+ Entity ServiceInstance
57
+ serviceId: string
58
+ host: string
59
+ port: integer
60
+ healthStatus: string
61
+ metadata: dict
62
+ registeredAt: datetime
63
+ lastHeartbeat: datetime
64
+ version: string
65
+ weight: integer
66
+
67
+ Entity ApiRoute
68
+ routeId: string
69
+ pathPattern: string
70
+ targetService: string
71
+ methods: list
72
+ rateLimit: integer
73
+ authRequired: boolean
74
+ timeout: integer
75
+ retryPolicy: dict
76
+
77
+ Entity CircuitBreaker
78
+ breakerId: string
79
+ serviceName: string
80
+ state: string
81
+ failureCount: integer
82
+ successCount: integer
83
+ lastFailureAt: datetime
84
+ openDuration: integer
85
+ halfOpenMaxCalls: integer
86
+
87
+ Entity SagaInstance
88
+ sagaId: string
89
+ sagaType: string
90
+ currentState: string
91
+ steps: list
92
+ completedSteps: list
93
+ compensateSteps: list
94
+ startedAt: datetime
95
+ timeoutAt: datetime
96
+ participantServices: list
97
+
98
+ Entity TraceSpan
99
+ traceId: string
100
+ spanId: string
101
+ parentSpanId: string
102
+ serviceName: string
103
+ operationName: string
104
+ startTime: datetime
105
+ endTime: datetime
106
+ tags: dict
107
+ status: string
108
+
109
+ Entity ServiceMetric
110
+ metricId: string
111
+ serviceName: string
112
+ metricName: string
113
+ value: float
114
+ timestamp: datetime
115
+ unit: string
116
+ tags: dict
117
+ percentile: float
118
+
119
+ # Level 3: Behaviors
120
+ Behavior RegisterService
121
+ Input:
122
+ instance: ServiceInstance
123
+ Output:
124
+ registrationId: string
125
+ Action:
126
+ Validate instance fields and health endpoint
127
+ Check for duplicate serviceId and host:port combination
128
+ Register in service discovery with TTL of 10 seconds
129
+ Broadcast registration event to all gateway replicas
130
+ Initialize circuit breaker for new service
131
+ Return registration confirmation
132
+
133
+ Behavior RouteRequest
134
+ Input:
135
+ route: ApiRoute
136
+ payload: dict
137
+ headers: dict
138
+ Output:
139
+ response: dict
140
+ latency: integer
141
+ Action:
142
+ Match incoming path and method to route definition
143
+ Check rate limit and authentication requirements
144
+ Resolve target service instance via discovery
145
+ Evaluate circuit breaker state before forwarding
146
+ Inject trace context headers
147
+ Forward request with timeout enforcement
148
+ Record latency metric and trace span
149
+
150
+ Behavior ExecuteSaga
151
+ Input:
152
+ sagaType: string
153
+ payload: dict
154
+ Output:
155
+ sagaId: string
156
+ status: string
157
+ Action:
158
+ Create saga instance with ordered steps
159
+ Begin first step and mark as in-progress
160
+ On step completion, advance to next step
161
+ On step failure, execute compensating actions in reverse
162
+ Persist saga state at each transition
163
+ Emit saga completion or compensation event
164
+
165
+ Behavior HandleCircuitBreaker
166
+ Input:
167
+ serviceName: string
168
+ result: string
169
+ latency: integer
170
+ Output:
171
+ newState: string
172
+ Action:
173
+ Record success or failure against breaker counters
174
+ If failure threshold exceeded, transition to Open state
175
+ If in Open state and cooldown elapsed, transition to HalfOpen
176
+ If HalfOpen and success threshold met, transition to Closed
177
+ If HalfOpen and failure detected, transition back to Open
178
+ Emit state change event to observability layer
179
+
180
+ Behavior DiscoverService
181
+ Input:
182
+ serviceName: string
183
+ version: string
184
+ region: string
185
+ Output:
186
+ instances: list
187
+ Action:
188
+ Query registry for matching service entries
189
+ Filter by version compatibility and region
190
+ Apply load-balancing weight to instance selection
191
+ Verify health status of returned instances
192
+ Return healthy instance list sorted by latency
193
+
194
+ Behavior CollectTrace
195
+ Input:
196
+ span: TraceSpan
197
+ Output:
198
+ accepted: boolean
199
+ Action:
200
+ Validate trace and span IDs are present
201
+ Link span to parent if parentSpanId exists
202
+ Calculate span duration from start and end times
203
+ Store span in trace backend
204
+ Check for trace completion (all spans received)
205
+ Emit trace-complete event if root span received
206
+
207
+ # Level 4: Conditions
208
+ Condition: ServiceUnhealthy
209
+ When service instance misses 3 consecutive heartbeats
210
+ Then mark instance as unhealthy and remove from active routing pool
211
+
212
+ Condition: RateLimitExceeded
213
+ When request count per minute exceeds route rateLimit threshold
214
+ Then return HTTP 429 with retry-after header and log throttle event
215
+
216
+ Condition: SagaTimeout
217
+ When saga execution exceeds timeoutAt without completion
218
+ Then trigger compensating transactions for all completed steps and mark saga as timed_out
219
+
220
+ # Level 5: Events
221
+ Event: OnServiceRegistered
222
+ On new service instance registered in discovery
223
+ Action: Update API gateway route table and warm connection pool to new instance
224
+
225
+ Event: OnCircuitBreakerStateChanged
226
+ On circuit breaker transitions between Open, Closed, or HalfOpen states
227
+ Action: Notify monitoring system and adjust routing weights away from degraded service
228
+
229
+ Event: OnSagaStepCompleted
230
+ On a saga participant confirms step completion
231
+ Action: Advance saga state machine and dispatch next step to next participant
232
+
233
+ Event: OnTraceAnomaly
234
+ On trace duration exceeds SLO threshold or error rate spikes
235
+ Action: Create incident alert and trigger automated diagnostic collection
236
+
237
+ # Level 6: Concurrency
238
+ Parallel:
239
+ Service health monitoring across all registered instances
240
+ Metrics aggregation from all services into centralized time-series store
241
+ Log streaming from all service containers to log collector
242
+ Circuit breaker state evaluation for all downstream connections
243
+ Trace span ingestion and parent-child linking across services
244
+
245
+ # Level 7: Optimization
246
+ Optimize: Inter-service call latency
247
+ Priority: Prefer collocated instances in same availability zone; then by lowest p99 latency history
248
+
249
+ Optimize: Gateway routing efficiency
250
+ Priority: Cache route lookups with LRU eviction; pre-warm connections to top percentile services
251
+
252
+ # Level 8: Learning
253
+ Learn: Service failure patterns
254
+ Goal: Predict circuit breaker trips before they occur based on latency and error rate trends
255
+ Adapt: Circuit breaker thresholds
256
+ Based: Historical failure pattern analysis across sliding 1-hour window
257
+
258
+ Learn: Optimal retry backoff intervals
259
+ Goal: Minimize retry storm risk while maximizing recovery speed
260
+ Adapt: Retry backoff multiplier and max retry count
261
+ Based: Downstream service recovery time distributions and error categorization
262
+
263
+ # Level 9: Security
264
+ Security:
265
+ Encrypt: All inter-service communication via mutual TLS with certificate rotation every 24 hours
266
+ Encrypt: Saga state payload containing PII using AES-256-GCM envelope encryption
267
+ Protect: API gateway against SQL injection, XSS, and request smuggling via WAF rules
268
+ Protect: Service registry from unauthorized writes with RBAC and signed registrations
269
+ Protect: Trace data from leaking sensitive headers by applying redaction rules
270
+
271
+ # Level 10: Native
272
+ Native: Python
273
+ {
274
+ import asyncio
275
+ from dataclasses import dataclass, field
276
+ from typing import Optional, Dict, List
277
+ from enum import Enum
278
+ import time
279
+
280
+ class BreakerState(Enum):
281
+ CLOSED = "closed"
282
+ OPEN = "open"
283
+ HALF_OPEN = "half_open"
284
+
285
+ @dataclass
286
+ class CircuitBreakerConfig:
287
+ failure_threshold: int = 5
288
+ success_threshold: int = 3
289
+ open_duration_seconds: int = 30
290
+ half_open_max_calls: int = 2
291
+
292
+ class CircuitBreaker:
293
+ def __init__(self, service_name: str, config: CircuitBreakerConfig = None):
294
+ self.service_name = service_name
295
+ self.config = config or CircuitBreakerConfig()
296
+ self.state = BreakerState.CLOSED
297
+ self.failure_count = 0
298
+ self.success_count = 0
299
+ self.last_failure_time: Optional[float] = None
300
+ self.half_open_calls = 0
301
+
302
+ def record_success(self):
303
+ if self.state == BreakerState.HALF_OPEN:
304
+ self.success_count += 1
305
+ if self.success_count >= self.config.success_threshold:
306
+ self.state = BreakerState.CLOSED
307
+ self.failure_count = 0
308
+ self.success_count = 0
309
+ elif self.state == BreakerState.CLOSED:
310
+ self.failure_count = max(0, self.failure_count - 1)
311
+
312
+ def record_failure(self):
313
+ self.failure_count += 1
314
+ self.last_failure_time = time.time()
315
+ if self.state == BreakerState.HALF_OPEN:
316
+ self.state = BreakerState.OPEN
317
+ self.success_count = 0
318
+ elif self.state == BreakerState.CLOSED:
319
+ if self.failure_count >= self.config.failure_threshold:
320
+ self.state = BreakerState.OPEN
321
+
322
+ def can_execute(self) -> bool:
323
+ if self.state == BreakerState.CLOSED:
324
+ return True
325
+ if self.state == BreakerState.OPEN:
326
+ if self.last_failure_time and \
327
+ (time.time() - self.last_failure_time) >= self.config.open_duration_seconds:
328
+ self.state = BreakerState.HALF_OPEN
329
+ self.success_count = 0
330
+ self.half_open_calls = 0
331
+ return True
332
+ return False
333
+ if self.state == BreakerState.HALF_OPEN:
334
+ return self.half_open_calls < self.config.half_open_max_calls
335
+ return False
336
+
337
+ class SagaOrchestrator:
338
+ def __init__(self):
339
+ self.sagas: Dict[str, dict] = {}
340
+
341
+ async def execute_saga(self, saga_id: str, steps: List[dict]):
342
+ self.sagas[saga_id] = {
343
+ "steps": steps, "completed": [], "status": "running"
344
+ }
345
+ for i, step in enumerate(steps):
346
+ try:
347
+ result = await step["action"]()
348
+ self.sagas[saga_id]["completed"].append(i)
349
+ except Exception as e:
350
+ self.sagas[saga_id]["status"] = "compensating"
351
+ await self._compensate(saga_id)
352
+ raise
353
+
354
+ async def _compensate(self, saga_id: str):
355
+ saga = self.sagas[saga_id]
356
+ for idx in reversed(saga["completed"]):
357
+ compensate = saga["steps"][idx].get("compensate")
358
+ if compensate:
359
+ try:
360
+ await compensate()
361
+ except Exception:
362
+ pass
363
+ saga["status"] = "compensated"
364
+
365
+ breaker = CircuitBreaker("payment-service")
366
+ if breaker.can_execute():
367
+ print(f"Circuit is {breaker.state.value}, request allowed")
368
+ }