@almadar/std 2.1.1 → 2.4.1
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/dist/behaviors/async.d.ts +12 -7
- package/dist/behaviors/async.js +1085 -312
- package/dist/behaviors/async.js.map +1 -1
- package/dist/behaviors/data-management.d.ts +27 -13
- package/dist/behaviors/data-management.js +600 -244
- package/dist/behaviors/data-management.js.map +1 -1
- package/dist/behaviors/domain/commerce.d.ts +51 -0
- package/dist/behaviors/domain/commerce.js +1093 -0
- package/dist/behaviors/domain/commerce.js.map +1 -0
- package/dist/behaviors/domain/content.d.ts +51 -0
- package/dist/behaviors/domain/content.js +1294 -0
- package/dist/behaviors/domain/content.js.map +1 -0
- package/dist/behaviors/domain/dashboard.d.ts +45 -0
- package/dist/behaviors/domain/dashboard.js +783 -0
- package/dist/behaviors/domain/dashboard.js.map +1 -0
- package/dist/behaviors/domain/education.d.ts +41 -0
- package/dist/behaviors/domain/education.js +738 -0
- package/dist/behaviors/domain/education.js.map +1 -0
- package/dist/behaviors/domain/finance.d.ts +49 -0
- package/dist/behaviors/domain/finance.js +660 -0
- package/dist/behaviors/domain/finance.js.map +1 -0
- package/dist/behaviors/domain/game-2d-platformer.d.ts +50 -0
- package/dist/behaviors/domain/game-2d-platformer.js +810 -0
- package/dist/behaviors/domain/game-2d-platformer.js.map +1 -0
- package/dist/behaviors/domain/game-2d-puzzle.d.ts +42 -0
- package/dist/behaviors/domain/game-2d-puzzle.js +622 -0
- package/dist/behaviors/domain/game-2d-puzzle.js.map +1 -0
- package/dist/behaviors/domain/game-2d-rpg.d.ts +48 -0
- package/dist/behaviors/domain/game-2d-rpg.js +860 -0
- package/dist/behaviors/domain/game-2d-rpg.js.map +1 -0
- package/dist/behaviors/domain/game-2d-strategy.d.ts +48 -0
- package/dist/behaviors/domain/game-2d-strategy.js +692 -0
- package/dist/behaviors/domain/game-2d-strategy.js.map +1 -0
- package/dist/behaviors/domain/geospatial.d.ts +35 -0
- package/dist/behaviors/domain/geospatial.js +634 -0
- package/dist/behaviors/domain/geospatial.js.map +1 -0
- package/dist/behaviors/domain/healthcare.d.ts +36 -0
- package/dist/behaviors/domain/healthcare.js +1068 -0
- package/dist/behaviors/domain/healthcare.js.map +1 -0
- package/dist/behaviors/domain/iot.d.ts +45 -0
- package/dist/behaviors/domain/iot.js +589 -0
- package/dist/behaviors/domain/iot.js.map +1 -0
- package/dist/behaviors/domain/media.d.ts +41 -0
- package/dist/behaviors/domain/media.js +771 -0
- package/dist/behaviors/domain/media.js.map +1 -0
- package/dist/behaviors/domain/scheduling.d.ts +41 -0
- package/dist/behaviors/domain/scheduling.js +930 -0
- package/dist/behaviors/domain/scheduling.js.map +1 -0
- package/dist/behaviors/domain/simulation.d.ts +36 -0
- package/dist/behaviors/domain/simulation.js +706 -0
- package/dist/behaviors/domain/simulation.js.map +1 -0
- package/dist/behaviors/domain/social.d.ts +41 -0
- package/dist/behaviors/domain/social.js +840 -0
- package/dist/behaviors/domain/social.js.map +1 -0
- package/dist/behaviors/domain/workflow.d.ts +41 -0
- package/dist/behaviors/domain/workflow.js +879 -0
- package/dist/behaviors/domain/workflow.js.map +1 -0
- package/dist/behaviors/feedback.d.ts +10 -5
- package/dist/behaviors/feedback.js +279 -194
- package/dist/behaviors/feedback.js.map +1 -1
- package/dist/behaviors/game-core.d.ts +15 -8
- package/dist/behaviors/game-core.js +412 -80
- package/dist/behaviors/game-core.js.map +1 -1
- package/dist/behaviors/game-entity.d.ts +17 -10
- package/dist/behaviors/game-entity.js +544 -237
- package/dist/behaviors/game-entity.js.map +1 -1
- package/dist/behaviors/game-ui.d.ts +16 -8
- package/dist/behaviors/game-ui.js +451 -316
- package/dist/behaviors/game-ui.js.map +1 -1
- package/dist/behaviors/index.d.ts +18 -1
- package/dist/behaviors/index.js +18905 -2140
- package/dist/behaviors/index.js.map +1 -1
- package/dist/behaviors/infrastructure.d.ts +9 -8
- package/dist/behaviors/infrastructure.js +597 -169
- package/dist/behaviors/infrastructure.js.map +1 -1
- package/dist/behaviors/registry.d.ts +11 -11
- package/dist/behaviors/registry.js +18904 -2139
- package/dist/behaviors/registry.js.map +1 -1
- package/dist/behaviors/types.d.ts +19 -2
- package/dist/behaviors/types.js.map +1 -1
- package/dist/behaviors/ui-interaction.d.ts +20 -14
- package/dist/behaviors/ui-interaction.js +928 -518
- package/dist/behaviors/ui-interaction.js.map +1 -1
- package/dist/index.js +18906 -2141
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,251 @@
|
|
|
1
1
|
// behaviors/infrastructure.ts
|
|
2
|
+
var INFRA_THEME = {
|
|
3
|
+
name: "infra-stone",
|
|
4
|
+
tokens: {
|
|
5
|
+
colors: {
|
|
6
|
+
primary: "#57534e",
|
|
7
|
+
"primary-hover": "#44403c",
|
|
8
|
+
"primary-foreground": "#ffffff",
|
|
9
|
+
accent: "#78716c",
|
|
10
|
+
"accent-foreground": "#ffffff",
|
|
11
|
+
success: "#22c55e",
|
|
12
|
+
warning: "#f59e0b",
|
|
13
|
+
error: "#ef4444"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
var circuitBreakerMainView = ["render-ui", "main", {
|
|
18
|
+
type: "stack",
|
|
19
|
+
direction: "vertical",
|
|
20
|
+
gap: "lg",
|
|
21
|
+
children: [
|
|
22
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
23
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
24
|
+
{ type: "icon", name: "shield-check", size: "lg" },
|
|
25
|
+
{ type: "typography", content: "Circuit Breaker", variant: "h2" }
|
|
26
|
+
] },
|
|
27
|
+
{ type: "badge", label: "@entity.circuitState", icon: "circle-dot", variant: "success" }
|
|
28
|
+
] },
|
|
29
|
+
{ type: "divider" },
|
|
30
|
+
{ type: "progress-bar", value: "@entity.errorCount", max: "@entity.errorThreshold", label: "Error Rate" },
|
|
31
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
32
|
+
{ type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
|
|
33
|
+
{ type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
|
|
34
|
+
{ type: "stat-card", label: "Total", value: "@entity.totalCount", icon: "hash" },
|
|
35
|
+
{ type: "stat-card", label: "Threshold", value: "@entity.errorThreshold", icon: "alert-triangle" }
|
|
36
|
+
] },
|
|
37
|
+
{ type: "divider" },
|
|
38
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
39
|
+
{ type: "button", label: "Simulate Success", action: "SUCCESS", icon: "check", variant: "primary" },
|
|
40
|
+
{ type: "button", label: "Simulate Failure", action: "FAILURE", icon: "x", variant: "secondary" },
|
|
41
|
+
{ type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
|
|
42
|
+
] }
|
|
43
|
+
]
|
|
44
|
+
}];
|
|
45
|
+
var circuitBreakerOpenView = ["render-ui", "main", {
|
|
46
|
+
type: "stack",
|
|
47
|
+
direction: "vertical",
|
|
48
|
+
gap: "lg",
|
|
49
|
+
children: [
|
|
50
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
51
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
52
|
+
{ type: "icon", name: "shield-alert", size: "lg" },
|
|
53
|
+
{ type: "typography", content: "Circuit Breaker - OPEN", variant: "h2" }
|
|
54
|
+
] },
|
|
55
|
+
{ type: "badge", label: "OPEN", icon: "alert-circle", variant: "danger" }
|
|
56
|
+
] },
|
|
57
|
+
{ type: "divider" },
|
|
58
|
+
{ type: "progress-bar", value: "@entity.errorCount", max: "@entity.errorThreshold", label: "Errors" },
|
|
59
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
60
|
+
{ type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
|
|
61
|
+
{ type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
|
|
62
|
+
{ type: "stat-card", label: "Total", value: "@entity.totalCount", icon: "hash" },
|
|
63
|
+
{ type: "stat-card", label: "Error Rate", value: "@entity.errorRate", icon: "percent" }
|
|
64
|
+
] },
|
|
65
|
+
{ type: "divider" },
|
|
66
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
67
|
+
{ type: "button", label: "Try Half-Open", action: "HALF_OPEN", icon: "shield-question", variant: "primary" },
|
|
68
|
+
{ type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
|
|
69
|
+
] }
|
|
70
|
+
]
|
|
71
|
+
}];
|
|
72
|
+
var circuitBreakerHalfOpenView = ["render-ui", "main", {
|
|
73
|
+
type: "stack",
|
|
74
|
+
direction: "vertical",
|
|
75
|
+
gap: "lg",
|
|
76
|
+
children: [
|
|
77
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
78
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
79
|
+
{ type: "icon", name: "shield-question", size: "lg" },
|
|
80
|
+
{ type: "typography", content: "Circuit Breaker - Half Open", variant: "h2" }
|
|
81
|
+
] },
|
|
82
|
+
{ type: "badge", label: "HALF-OPEN", icon: "alert-triangle", variant: "warning" }
|
|
83
|
+
] },
|
|
84
|
+
{ type: "divider" },
|
|
85
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
86
|
+
{ type: "stat-card", label: "Errors", value: "@entity.errorCount", icon: "x-circle" },
|
|
87
|
+
{ type: "stat-card", label: "Successes", value: "@entity.successCount", icon: "check-circle" },
|
|
88
|
+
{ type: "stat-card", label: "Attempts", value: "@entity.halfOpenAttempts", icon: "rotate-cw" },
|
|
89
|
+
{ type: "stat-card", label: "Error Rate", value: "@entity.errorRate", icon: "percent" }
|
|
90
|
+
] },
|
|
91
|
+
{ type: "divider" },
|
|
92
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
93
|
+
{ type: "button", label: "Test Success", action: "SUCCESS", icon: "check", variant: "primary" },
|
|
94
|
+
{ type: "button", label: "Test Failure", action: "FAILURE", icon: "x", variant: "secondary" }
|
|
95
|
+
] }
|
|
96
|
+
]
|
|
97
|
+
}];
|
|
98
|
+
var healthCheckView = (title, statusVariant) => ["render-ui", "main", {
|
|
99
|
+
type: "stack",
|
|
100
|
+
direction: "vertical",
|
|
101
|
+
gap: "lg",
|
|
102
|
+
children: [
|
|
103
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
104
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
105
|
+
{ type: "icon", name: "activity", size: "lg" },
|
|
106
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
107
|
+
] },
|
|
108
|
+
{ type: "badge", label: "@entity.healthStatus", icon: "heart-pulse", variant: statusVariant }
|
|
109
|
+
] },
|
|
110
|
+
{ type: "divider" },
|
|
111
|
+
{ type: "progress-bar", value: "@entity.consecutiveFailures", max: "@entity.unhealthyThreshold", label: "Failure Threshold" },
|
|
112
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
113
|
+
{ type: "stat-card", label: "Failures", value: "@entity.consecutiveFailures", icon: "x-circle" },
|
|
114
|
+
{ type: "stat-card", label: "Successes", value: "@entity.consecutiveSuccesses", icon: "check-circle" },
|
|
115
|
+
{ type: "stat-card", label: "Total Checks", value: "@entity.totalChecks", icon: "clipboard-check" },
|
|
116
|
+
{ type: "stat-card", label: "Total Failures", value: "@entity.totalFailures", icon: "alert-triangle" }
|
|
117
|
+
] },
|
|
118
|
+
{ type: "divider" },
|
|
119
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
120
|
+
{ type: "button", label: "Check Success", action: "CHECK_SUCCESS", icon: "check", variant: "primary" },
|
|
121
|
+
{ type: "button", label: "Check Failure", action: "CHECK_FAILURE", icon: "x", variant: "secondary" },
|
|
122
|
+
{ type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
|
|
123
|
+
] }
|
|
124
|
+
]
|
|
125
|
+
}];
|
|
126
|
+
var rateLimiterView = (title) => ["render-ui", "main", {
|
|
127
|
+
type: "stack",
|
|
128
|
+
direction: "vertical",
|
|
129
|
+
gap: "lg",
|
|
130
|
+
children: [
|
|
131
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
132
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
133
|
+
{ type: "icon", name: "gauge", size: "lg" },
|
|
134
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
135
|
+
] }
|
|
136
|
+
] },
|
|
137
|
+
{ type: "divider" },
|
|
138
|
+
{ type: "progress-bar", value: "@entity.requestCount", max: "@entity.rateLimit", label: "Rate Usage" },
|
|
139
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
140
|
+
{ type: "stat-card", label: "Requests", value: "@entity.requestCount", icon: "arrow-up-right" },
|
|
141
|
+
{ type: "stat-card", label: "Limit", value: "@entity.rateLimit", icon: "shield" },
|
|
142
|
+
{ type: "stat-card", label: "Total", value: "@entity.totalRequests", icon: "hash" },
|
|
143
|
+
{ type: "stat-card", label: "Rejected", value: "@entity.rejectedRequests", icon: "ban" }
|
|
144
|
+
] },
|
|
145
|
+
{ type: "divider" },
|
|
146
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
147
|
+
{ type: "button", label: "Send Request", action: "REQUEST", icon: "send", variant: "primary" },
|
|
148
|
+
{ type: "button", label: "Reset Window", action: "RESET_WINDOW", icon: "refresh-cw", variant: "secondary" }
|
|
149
|
+
] }
|
|
150
|
+
]
|
|
151
|
+
}];
|
|
152
|
+
var cacheStatsView = (title) => ["render-ui", "main", {
|
|
153
|
+
type: "stack",
|
|
154
|
+
direction: "vertical",
|
|
155
|
+
gap: "lg",
|
|
156
|
+
children: [
|
|
157
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
158
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
159
|
+
{ type: "icon", name: "database", size: "lg" },
|
|
160
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
161
|
+
] },
|
|
162
|
+
{ type: "badge", label: "@entity.isFresh", icon: "check-circle", variant: "outline" }
|
|
163
|
+
] },
|
|
164
|
+
{ type: "divider" },
|
|
165
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
166
|
+
{ type: "stat-card", label: "Key", value: "@entity.cacheKey", icon: "key" },
|
|
167
|
+
{ type: "stat-card", label: "Hits", value: "@entity.cacheHits", icon: "check" },
|
|
168
|
+
{ type: "stat-card", label: "Misses", value: "@entity.cacheMisses", icon: "x" },
|
|
169
|
+
{ type: "stat-card", label: "TTL (ms)", value: "@entity.ttlMs", icon: "clock" }
|
|
170
|
+
] },
|
|
171
|
+
{ type: "divider" },
|
|
172
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
173
|
+
{ type: "button", label: "Get", action: "GET", icon: "download", variant: "primary" },
|
|
174
|
+
{ type: "button", label: "Invalidate", action: "INVALIDATE", icon: "trash-2", variant: "secondary" }
|
|
175
|
+
] }
|
|
176
|
+
]
|
|
177
|
+
}];
|
|
178
|
+
var cacheEmptyView = (title) => ["render-ui", "main", {
|
|
179
|
+
type: "stack",
|
|
180
|
+
direction: "vertical",
|
|
181
|
+
gap: "lg",
|
|
182
|
+
children: [
|
|
183
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
184
|
+
{ type: "icon", name: "database", size: "lg" },
|
|
185
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
186
|
+
] },
|
|
187
|
+
{ type: "divider" },
|
|
188
|
+
{ type: "empty-state", icon: "inbox", title: "Cache is empty", description: "No cached data available" },
|
|
189
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
190
|
+
{ type: "stat-card", label: "Hits", value: "@entity.cacheHits", icon: "check" },
|
|
191
|
+
{ type: "stat-card", label: "Misses", value: "@entity.cacheMisses", icon: "x" }
|
|
192
|
+
] },
|
|
193
|
+
{ type: "divider" },
|
|
194
|
+
{ type: "button", label: "Fetch Data", action: "SET", icon: "download", variant: "primary" }
|
|
195
|
+
]
|
|
196
|
+
}];
|
|
197
|
+
var sagaView = (title) => ["render-ui", "main", {
|
|
198
|
+
type: "stack",
|
|
199
|
+
direction: "vertical",
|
|
200
|
+
gap: "lg",
|
|
201
|
+
children: [
|
|
202
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
203
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
204
|
+
{ type: "icon", name: "workflow", size: "lg" },
|
|
205
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
206
|
+
] },
|
|
207
|
+
{ type: "badge", label: "@entity.sagaStatus", icon: "flag", variant: "outline" }
|
|
208
|
+
] },
|
|
209
|
+
{ type: "divider" },
|
|
210
|
+
{ type: "progress-bar", value: "@entity.currentStep", max: "@entity.totalSteps", label: "Progress" },
|
|
211
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
212
|
+
{ type: "stat-card", label: "Current Step", value: "@entity.currentStep", icon: "footprints" },
|
|
213
|
+
{ type: "stat-card", label: "Total Steps", value: "@entity.totalSteps", icon: "list-ordered" },
|
|
214
|
+
{ type: "stat-card", label: "Failed Step", value: "@entity.failedStep", icon: "alert-circle" },
|
|
215
|
+
{ type: "stat-card", label: "Status", value: "@entity.sagaStatus", icon: "flag" }
|
|
216
|
+
] },
|
|
217
|
+
{ type: "divider" },
|
|
218
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
219
|
+
{ type: "button", label: "Execute", action: "EXECUTE", icon: "play", variant: "primary" },
|
|
220
|
+
{ type: "button", label: "Compensate", action: "COMPENSATE", icon: "undo-2", variant: "secondary" },
|
|
221
|
+
{ type: "button", label: "Reset", action: "RESET", icon: "refresh-cw", variant: "secondary" }
|
|
222
|
+
] }
|
|
223
|
+
]
|
|
224
|
+
}];
|
|
225
|
+
var metricsView = (title) => ["render-ui", "main", {
|
|
226
|
+
type: "stack",
|
|
227
|
+
direction: "vertical",
|
|
228
|
+
gap: "lg",
|
|
229
|
+
children: [
|
|
230
|
+
{ type: "stack", direction: "horizontal", justify: "space-between", children: [
|
|
231
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
232
|
+
{ type: "icon", name: "bar-chart-3", size: "lg" },
|
|
233
|
+
{ type: "typography", content: title, variant: "h2" }
|
|
234
|
+
] }
|
|
235
|
+
] },
|
|
236
|
+
{ type: "divider" },
|
|
237
|
+
{ type: "stack", direction: "horizontal", gap: "md", children: [
|
|
238
|
+
{ type: "stat-card", label: "Recorded", value: "@entity.totalRecorded", icon: "database" },
|
|
239
|
+
{ type: "stat-card", label: "Flushes", value: "@entity.totalFlushes", icon: "upload" },
|
|
240
|
+
{ type: "stat-card", label: "Last Flush", value: "@entity.lastFlush", icon: "clock" }
|
|
241
|
+
] },
|
|
242
|
+
{ type: "divider" },
|
|
243
|
+
{ type: "stack", direction: "horizontal", gap: "sm", children: [
|
|
244
|
+
{ type: "button", label: "Record", action: "RECORD", icon: "plus", variant: "primary" },
|
|
245
|
+
{ type: "button", label: "Flush", action: "FLUSH", icon: "upload", variant: "secondary" }
|
|
246
|
+
] }
|
|
247
|
+
]
|
|
248
|
+
}];
|
|
2
249
|
var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
3
250
|
name: "std-circuit-breaker",
|
|
4
251
|
version: "1.0.0",
|
|
@@ -6,6 +253,7 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
6
253
|
orbitals: [
|
|
7
254
|
{
|
|
8
255
|
name: "CircuitBreakerOrbital",
|
|
256
|
+
theme: INFRA_THEME,
|
|
9
257
|
entity: {
|
|
10
258
|
name: "CircuitBreakerState",
|
|
11
259
|
persistence: "runtime",
|
|
@@ -16,8 +264,8 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
16
264
|
{ name: "errorRate", type: "number", default: 0 },
|
|
17
265
|
{ name: "successCount", type: "number", default: 0 },
|
|
18
266
|
{ name: "totalCount", type: "number", default: 0 },
|
|
19
|
-
{ name: "lastFailure", type: "number", default:
|
|
20
|
-
{ name: "lastSuccess", type: "number", default:
|
|
267
|
+
{ name: "lastFailure", type: "number", default: 0 },
|
|
268
|
+
{ name: "lastSuccess", type: "number", default: 0 },
|
|
21
269
|
{ name: "errorThreshold", type: "number", default: 5 },
|
|
22
270
|
{ name: "errorRateThreshold", type: "number", default: 0.5 },
|
|
23
271
|
{ name: "resetAfterMs", type: "number", default: 6e4 },
|
|
@@ -29,12 +277,7 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
29
277
|
{
|
|
30
278
|
name: "CircuitBreaker",
|
|
31
279
|
linkedEntity: "CircuitBreakerState",
|
|
32
|
-
category: "
|
|
33
|
-
emits: [
|
|
34
|
-
{ event: "CIRCUIT_OPENED", scope: "external" },
|
|
35
|
-
{ event: "CIRCUIT_CLOSED", scope: "external" },
|
|
36
|
-
{ event: "CIRCUIT_HALF_OPEN", scope: "external" }
|
|
37
|
-
],
|
|
280
|
+
category: "interaction",
|
|
38
281
|
stateMachine: {
|
|
39
282
|
states: [
|
|
40
283
|
{ name: "Closed", isInitial: true },
|
|
@@ -42,22 +285,35 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
42
285
|
{ name: "HalfOpen" }
|
|
43
286
|
],
|
|
44
287
|
events: [
|
|
288
|
+
{ key: "INIT", name: "Initialize" },
|
|
45
289
|
{ key: "RECORD_SUCCESS", name: "Record Success" },
|
|
46
290
|
{ key: "RECORD_FAILURE", name: "Record Failure" },
|
|
47
291
|
{ key: "PROBE", name: "Probe" },
|
|
48
292
|
{ key: "RESET", name: "Reset" }
|
|
49
293
|
],
|
|
50
294
|
transitions: [
|
|
295
|
+
// INIT: render dashboard
|
|
296
|
+
{
|
|
297
|
+
from: "Closed",
|
|
298
|
+
to: "Closed",
|
|
299
|
+
event: "INIT",
|
|
300
|
+
effects: [
|
|
301
|
+
["fetch", "CircuitBreakerState"],
|
|
302
|
+
circuitBreakerMainView
|
|
303
|
+
]
|
|
304
|
+
},
|
|
51
305
|
// Closed: record success
|
|
52
306
|
{
|
|
53
307
|
from: "Closed",
|
|
54
308
|
to: "Closed",
|
|
55
309
|
event: "RECORD_SUCCESS",
|
|
56
310
|
effects: [
|
|
311
|
+
["fetch", "CircuitBreakerState"],
|
|
57
312
|
["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
|
|
58
313
|
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
59
314
|
["set", "@entity.lastSuccess", ["time/now"]],
|
|
60
|
-
["set", "@entity.errorRate", ["/", "@entity.errorCount", ["math/max", "@entity.totalCount", 1]]]
|
|
315
|
+
["set", "@entity.errorRate", ["/", "@entity.errorCount", ["math/max", "@entity.totalCount", 1]]],
|
|
316
|
+
circuitBreakerMainView
|
|
61
317
|
]
|
|
62
318
|
},
|
|
63
319
|
// Closed: record failure, stay closed if under threshold
|
|
@@ -67,10 +323,12 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
67
323
|
event: "RECORD_FAILURE",
|
|
68
324
|
guard: ["<", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
|
|
69
325
|
effects: [
|
|
326
|
+
["fetch", "CircuitBreakerState"],
|
|
70
327
|
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
71
328
|
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
72
329
|
["set", "@entity.lastFailure", ["time/now"]],
|
|
73
|
-
["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]]
|
|
330
|
+
["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]],
|
|
331
|
+
circuitBreakerMainView
|
|
74
332
|
]
|
|
75
333
|
},
|
|
76
334
|
// Closed -> Open: threshold exceeded
|
|
@@ -80,11 +338,13 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
80
338
|
event: "RECORD_FAILURE",
|
|
81
339
|
guard: [">=", ["+", "@entity.errorCount", 1], "@entity.errorThreshold"],
|
|
82
340
|
effects: [
|
|
341
|
+
["fetch", "CircuitBreakerState"],
|
|
83
342
|
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
84
343
|
["set", "@entity.totalCount", ["+", "@entity.totalCount", 1]],
|
|
85
344
|
["set", "@entity.lastFailure", ["time/now"]],
|
|
86
345
|
["set", "@entity.errorRate", ["/", ["+", "@entity.errorCount", 1], ["math/max", "@entity.totalCount", 1]]],
|
|
87
|
-
["
|
|
346
|
+
["set", "@entity.circuitState", "open"],
|
|
347
|
+
circuitBreakerOpenView
|
|
88
348
|
]
|
|
89
349
|
},
|
|
90
350
|
// Open -> HalfOpen: probe after reset timeout
|
|
@@ -94,8 +354,10 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
94
354
|
event: "PROBE",
|
|
95
355
|
guard: [">", ["-", ["time/now"], "@entity.lastFailure"], "@entity.resetAfterMs"],
|
|
96
356
|
effects: [
|
|
357
|
+
["fetch", "CircuitBreakerState"],
|
|
97
358
|
["set", "@entity.halfOpenAttempts", 0],
|
|
98
|
-
["
|
|
359
|
+
["set", "@entity.circuitState", "halfOpen"],
|
|
360
|
+
circuitBreakerHalfOpenView
|
|
99
361
|
]
|
|
100
362
|
},
|
|
101
363
|
// HalfOpen: success -> close
|
|
@@ -104,12 +366,14 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
104
366
|
to: "Closed",
|
|
105
367
|
event: "RECORD_SUCCESS",
|
|
106
368
|
effects: [
|
|
369
|
+
["fetch", "CircuitBreakerState"],
|
|
107
370
|
["set", "@entity.errorCount", 0],
|
|
108
371
|
["set", "@entity.errorRate", 0],
|
|
109
372
|
["set", "@entity.halfOpenAttempts", 0],
|
|
110
373
|
["set", "@entity.successCount", ["+", "@entity.successCount", 1]],
|
|
111
374
|
["set", "@entity.lastSuccess", ["time/now"]],
|
|
112
|
-
["
|
|
375
|
+
["set", "@entity.circuitState", "closed"],
|
|
376
|
+
circuitBreakerMainView
|
|
113
377
|
]
|
|
114
378
|
},
|
|
115
379
|
// HalfOpen: failure -> back to open
|
|
@@ -118,23 +382,59 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
118
382
|
to: "Open",
|
|
119
383
|
event: "RECORD_FAILURE",
|
|
120
384
|
effects: [
|
|
385
|
+
["fetch", "CircuitBreakerState"],
|
|
121
386
|
["set", "@entity.errorCount", ["+", "@entity.errorCount", 1]],
|
|
122
387
|
["set", "@entity.lastFailure", ["time/now"]],
|
|
123
|
-
["
|
|
388
|
+
["set", "@entity.circuitState", "open"],
|
|
389
|
+
circuitBreakerOpenView
|
|
124
390
|
]
|
|
125
391
|
},
|
|
126
|
-
// Reset from
|
|
392
|
+
// Reset from Closed
|
|
127
393
|
{
|
|
128
|
-
from:
|
|
394
|
+
from: "Closed",
|
|
395
|
+
to: "Closed",
|
|
396
|
+
event: "RESET",
|
|
397
|
+
effects: [
|
|
398
|
+
["fetch", "CircuitBreakerState"],
|
|
399
|
+
["set", "@entity.errorCount", 0],
|
|
400
|
+
["set", "@entity.successCount", 0],
|
|
401
|
+
["set", "@entity.totalCount", 0],
|
|
402
|
+
["set", "@entity.errorRate", 0],
|
|
403
|
+
["set", "@entity.halfOpenAttempts", 0],
|
|
404
|
+
["set", "@entity.circuitState", "closed"],
|
|
405
|
+
circuitBreakerMainView
|
|
406
|
+
]
|
|
407
|
+
},
|
|
408
|
+
// Reset from Open
|
|
409
|
+
{
|
|
410
|
+
from: "Open",
|
|
129
411
|
to: "Closed",
|
|
130
412
|
event: "RESET",
|
|
131
413
|
effects: [
|
|
414
|
+
["fetch", "CircuitBreakerState"],
|
|
132
415
|
["set", "@entity.errorCount", 0],
|
|
133
416
|
["set", "@entity.successCount", 0],
|
|
134
417
|
["set", "@entity.totalCount", 0],
|
|
135
418
|
["set", "@entity.errorRate", 0],
|
|
136
419
|
["set", "@entity.halfOpenAttempts", 0],
|
|
137
|
-
["set", "@entity.circuitState", "closed"]
|
|
420
|
+
["set", "@entity.circuitState", "closed"],
|
|
421
|
+
circuitBreakerMainView
|
|
422
|
+
]
|
|
423
|
+
},
|
|
424
|
+
// Reset from HalfOpen
|
|
425
|
+
{
|
|
426
|
+
from: "HalfOpen",
|
|
427
|
+
to: "Closed",
|
|
428
|
+
event: "RESET",
|
|
429
|
+
effects: [
|
|
430
|
+
["fetch", "CircuitBreakerState"],
|
|
431
|
+
["set", "@entity.errorCount", 0],
|
|
432
|
+
["set", "@entity.successCount", 0],
|
|
433
|
+
["set", "@entity.totalCount", 0],
|
|
434
|
+
["set", "@entity.errorRate", 0],
|
|
435
|
+
["set", "@entity.halfOpenAttempts", 0],
|
|
436
|
+
["set", "@entity.circuitState", "closed"],
|
|
437
|
+
circuitBreakerMainView
|
|
138
438
|
]
|
|
139
439
|
}
|
|
140
440
|
]
|
|
@@ -142,15 +442,14 @@ var CIRCUIT_BREAKER_BEHAVIOR = {
|
|
|
142
442
|
ticks: [
|
|
143
443
|
{
|
|
144
444
|
name: "probe_half_open",
|
|
145
|
-
interval:
|
|
445
|
+
interval: 3e4,
|
|
146
446
|
guard: ["=", "@entity.circuitState", "open"],
|
|
147
|
-
effects: [
|
|
148
|
-
description: "Periodically probe to transition from Open to HalfOpen"
|
|
447
|
+
effects: []
|
|
149
448
|
}
|
|
150
449
|
]
|
|
151
450
|
}
|
|
152
451
|
],
|
|
153
|
-
pages: []
|
|
452
|
+
pages: [{ name: "CircuitBreakerPage", path: "/circuit-breaker", isInitial: true, traits: [{ ref: "CircuitBreaker" }] }]
|
|
154
453
|
}
|
|
155
454
|
]
|
|
156
455
|
};
|
|
@@ -161,17 +460,17 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
161
460
|
orbitals: [
|
|
162
461
|
{
|
|
163
462
|
name: "HealthCheckOrbital",
|
|
463
|
+
theme: INFRA_THEME,
|
|
164
464
|
entity: {
|
|
165
465
|
name: "HealthCheckState",
|
|
166
466
|
persistence: "runtime",
|
|
167
467
|
fields: [
|
|
168
468
|
{ name: "id", type: "string", required: true },
|
|
169
469
|
{ name: "healthStatus", type: "string", default: "unknown" },
|
|
170
|
-
{ name: "lastCheck", type: "number", default:
|
|
171
|
-
{ name: "lastHealthy", type: "number", default:
|
|
470
|
+
{ name: "lastCheck", type: "number", default: 0 },
|
|
471
|
+
{ name: "lastHealthy", type: "number", default: 0 },
|
|
172
472
|
{ name: "consecutiveFailures", type: "number", default: 0 },
|
|
173
473
|
{ name: "consecutiveSuccesses", type: "number", default: 0 },
|
|
174
|
-
{ name: "checkIntervalMs", type: "number", default: 3e4 },
|
|
175
474
|
{ name: "degradedThreshold", type: "number", default: 2 },
|
|
176
475
|
{ name: "unhealthyThreshold", type: "number", default: 5 },
|
|
177
476
|
{ name: "recoveryThreshold", type: "number", default: 3 },
|
|
@@ -183,12 +482,7 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
183
482
|
{
|
|
184
483
|
name: "HealthCheck",
|
|
185
484
|
linkedEntity: "HealthCheckState",
|
|
186
|
-
category: "
|
|
187
|
-
emits: [
|
|
188
|
-
{ event: "SERVICE_HEALTHY", scope: "external" },
|
|
189
|
-
{ event: "SERVICE_DEGRADED", scope: "external" },
|
|
190
|
-
{ event: "SERVICE_UNHEALTHY", scope: "external" }
|
|
191
|
-
],
|
|
485
|
+
category: "interaction",
|
|
192
486
|
stateMachine: {
|
|
193
487
|
states: [
|
|
194
488
|
{ name: "Unknown", isInitial: true },
|
|
@@ -197,25 +491,36 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
197
491
|
{ name: "Unhealthy" }
|
|
198
492
|
],
|
|
199
493
|
events: [
|
|
494
|
+
{ key: "INIT", name: "Initialize" },
|
|
200
495
|
{ key: "CHECK_SUCCESS", name: "Check Success" },
|
|
201
496
|
{ key: "CHECK_FAILURE", name: "Check Failure" },
|
|
202
|
-
{ key: "HEALTH_TICK", name: "Health Tick" },
|
|
203
497
|
{ key: "RESET", name: "Reset" }
|
|
204
498
|
],
|
|
205
499
|
transitions: [
|
|
500
|
+
// INIT
|
|
501
|
+
{
|
|
502
|
+
from: "Unknown",
|
|
503
|
+
to: "Unknown",
|
|
504
|
+
event: "INIT",
|
|
505
|
+
effects: [
|
|
506
|
+
["fetch", "HealthCheckState"],
|
|
507
|
+
healthCheckView("Health Check", "outline")
|
|
508
|
+
]
|
|
509
|
+
},
|
|
206
510
|
// Unknown -> Healthy on first success
|
|
207
511
|
{
|
|
208
512
|
from: "Unknown",
|
|
209
513
|
to: "Healthy",
|
|
210
514
|
event: "CHECK_SUCCESS",
|
|
211
515
|
effects: [
|
|
516
|
+
["fetch", "HealthCheckState"],
|
|
212
517
|
["set", "@entity.healthStatus", "healthy"],
|
|
213
518
|
["set", "@entity.consecutiveSuccesses", 1],
|
|
214
519
|
["set", "@entity.consecutiveFailures", 0],
|
|
215
520
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
216
521
|
["set", "@entity.lastHealthy", ["time/now"]],
|
|
217
522
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
218
|
-
|
|
523
|
+
healthCheckView("Health Check - Healthy", "success")
|
|
219
524
|
]
|
|
220
525
|
},
|
|
221
526
|
// Unknown -> Degraded on first failure
|
|
@@ -224,13 +529,14 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
224
529
|
to: "Degraded",
|
|
225
530
|
event: "CHECK_FAILURE",
|
|
226
531
|
effects: [
|
|
532
|
+
["fetch", "HealthCheckState"],
|
|
227
533
|
["set", "@entity.healthStatus", "degraded"],
|
|
228
534
|
["set", "@entity.consecutiveFailures", 1],
|
|
229
535
|
["set", "@entity.consecutiveSuccesses", 0],
|
|
230
536
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
231
537
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
232
538
|
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
233
|
-
|
|
539
|
+
healthCheckView("Health Check - Degraded", "warning")
|
|
234
540
|
]
|
|
235
541
|
},
|
|
236
542
|
// Healthy: stay healthy on success
|
|
@@ -239,11 +545,13 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
239
545
|
to: "Healthy",
|
|
240
546
|
event: "CHECK_SUCCESS",
|
|
241
547
|
effects: [
|
|
548
|
+
["fetch", "HealthCheckState"],
|
|
242
549
|
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
243
550
|
["set", "@entity.consecutiveFailures", 0],
|
|
244
551
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
245
552
|
["set", "@entity.lastHealthy", ["time/now"]],
|
|
246
|
-
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
|
|
553
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
554
|
+
healthCheckView("Health Check - Healthy", "success")
|
|
247
555
|
]
|
|
248
556
|
},
|
|
249
557
|
// Healthy -> Degraded on failure
|
|
@@ -252,13 +560,14 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
252
560
|
to: "Degraded",
|
|
253
561
|
event: "CHECK_FAILURE",
|
|
254
562
|
effects: [
|
|
563
|
+
["fetch", "HealthCheckState"],
|
|
255
564
|
["set", "@entity.healthStatus", "degraded"],
|
|
256
565
|
["set", "@entity.consecutiveFailures", 1],
|
|
257
566
|
["set", "@entity.consecutiveSuccesses", 0],
|
|
258
567
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
259
568
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
260
569
|
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
261
|
-
|
|
570
|
+
healthCheckView("Health Check - Degraded", "warning")
|
|
262
571
|
]
|
|
263
572
|
},
|
|
264
573
|
// Degraded: stay degraded on failure (below unhealthy threshold)
|
|
@@ -268,11 +577,13 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
268
577
|
event: "CHECK_FAILURE",
|
|
269
578
|
guard: ["<", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
|
|
270
579
|
effects: [
|
|
580
|
+
["fetch", "HealthCheckState"],
|
|
271
581
|
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
272
582
|
["set", "@entity.consecutiveSuccesses", 0],
|
|
273
583
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
274
584
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
275
|
-
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
|
|
585
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
586
|
+
healthCheckView("Health Check - Degraded", "warning")
|
|
276
587
|
]
|
|
277
588
|
},
|
|
278
589
|
// Degraded -> Unhealthy when threshold exceeded
|
|
@@ -282,12 +593,13 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
282
593
|
event: "CHECK_FAILURE",
|
|
283
594
|
guard: [">=", ["+", "@entity.consecutiveFailures", 1], "@entity.unhealthyThreshold"],
|
|
284
595
|
effects: [
|
|
596
|
+
["fetch", "HealthCheckState"],
|
|
285
597
|
["set", "@entity.healthStatus", "unhealthy"],
|
|
286
598
|
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
287
599
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
288
600
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
289
601
|
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
290
|
-
|
|
602
|
+
healthCheckView("Health Check - Unhealthy", "danger")
|
|
291
603
|
]
|
|
292
604
|
},
|
|
293
605
|
// Degraded -> Healthy on enough successes
|
|
@@ -297,13 +609,14 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
297
609
|
event: "CHECK_SUCCESS",
|
|
298
610
|
guard: [">=", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
|
|
299
611
|
effects: [
|
|
612
|
+
["fetch", "HealthCheckState"],
|
|
300
613
|
["set", "@entity.healthStatus", "healthy"],
|
|
301
614
|
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
302
615
|
["set", "@entity.consecutiveFailures", 0],
|
|
303
616
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
304
617
|
["set", "@entity.lastHealthy", ["time/now"]],
|
|
305
618
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
306
|
-
|
|
619
|
+
healthCheckView("Health Check - Healthy", "success")
|
|
307
620
|
]
|
|
308
621
|
},
|
|
309
622
|
// Degraded: stay degraded on success (not enough to recover)
|
|
@@ -313,10 +626,12 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
313
626
|
event: "CHECK_SUCCESS",
|
|
314
627
|
guard: ["<", ["+", "@entity.consecutiveSuccesses", 1], "@entity.recoveryThreshold"],
|
|
315
628
|
effects: [
|
|
629
|
+
["fetch", "HealthCheckState"],
|
|
316
630
|
["set", "@entity.consecutiveSuccesses", ["+", "@entity.consecutiveSuccesses", 1]],
|
|
317
631
|
["set", "@entity.consecutiveFailures", 0],
|
|
318
632
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
319
|
-
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]]
|
|
633
|
+
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
634
|
+
healthCheckView("Health Check - Degraded", "warning")
|
|
320
635
|
]
|
|
321
636
|
},
|
|
322
637
|
// Unhealthy: stay unhealthy on failure
|
|
@@ -325,10 +640,12 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
325
640
|
to: "Unhealthy",
|
|
326
641
|
event: "CHECK_FAILURE",
|
|
327
642
|
effects: [
|
|
643
|
+
["fetch", "HealthCheckState"],
|
|
328
644
|
["set", "@entity.consecutiveFailures", ["+", "@entity.consecutiveFailures", 1]],
|
|
329
645
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
330
646
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
331
|
-
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]]
|
|
647
|
+
["set", "@entity.totalFailures", ["+", "@entity.totalFailures", 1]],
|
|
648
|
+
healthCheckView("Health Check - Unhealthy", "danger")
|
|
332
649
|
]
|
|
333
650
|
},
|
|
334
651
|
// Unhealthy -> Degraded on first success (recovery begins)
|
|
@@ -337,25 +654,73 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
337
654
|
to: "Degraded",
|
|
338
655
|
event: "CHECK_SUCCESS",
|
|
339
656
|
effects: [
|
|
657
|
+
["fetch", "HealthCheckState"],
|
|
340
658
|
["set", "@entity.healthStatus", "degraded"],
|
|
341
659
|
["set", "@entity.consecutiveSuccesses", 1],
|
|
342
660
|
["set", "@entity.consecutiveFailures", 0],
|
|
343
661
|
["set", "@entity.lastCheck", ["time/now"]],
|
|
344
662
|
["set", "@entity.totalChecks", ["+", "@entity.totalChecks", 1]],
|
|
345
|
-
|
|
663
|
+
healthCheckView("Health Check - Degraded", "warning")
|
|
664
|
+
]
|
|
665
|
+
},
|
|
666
|
+
// Reset from Unknown
|
|
667
|
+
{
|
|
668
|
+
from: "Unknown",
|
|
669
|
+
to: "Unknown",
|
|
670
|
+
event: "RESET",
|
|
671
|
+
effects: [
|
|
672
|
+
["fetch", "HealthCheckState"],
|
|
673
|
+
["set", "@entity.healthStatus", "unknown"],
|
|
674
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
675
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
676
|
+
["set", "@entity.totalChecks", 0],
|
|
677
|
+
["set", "@entity.totalFailures", 0],
|
|
678
|
+
healthCheckView("Health Check", "outline")
|
|
679
|
+
]
|
|
680
|
+
},
|
|
681
|
+
// Reset from Healthy
|
|
682
|
+
{
|
|
683
|
+
from: "Healthy",
|
|
684
|
+
to: "Unknown",
|
|
685
|
+
event: "RESET",
|
|
686
|
+
effects: [
|
|
687
|
+
["fetch", "HealthCheckState"],
|
|
688
|
+
["set", "@entity.healthStatus", "unknown"],
|
|
689
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
690
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
691
|
+
["set", "@entity.totalChecks", 0],
|
|
692
|
+
["set", "@entity.totalFailures", 0],
|
|
693
|
+
healthCheckView("Health Check", "outline")
|
|
694
|
+
]
|
|
695
|
+
},
|
|
696
|
+
// Reset from Degraded
|
|
697
|
+
{
|
|
698
|
+
from: "Degraded",
|
|
699
|
+
to: "Unknown",
|
|
700
|
+
event: "RESET",
|
|
701
|
+
effects: [
|
|
702
|
+
["fetch", "HealthCheckState"],
|
|
703
|
+
["set", "@entity.healthStatus", "unknown"],
|
|
704
|
+
["set", "@entity.consecutiveFailures", 0],
|
|
705
|
+
["set", "@entity.consecutiveSuccesses", 0],
|
|
706
|
+
["set", "@entity.totalChecks", 0],
|
|
707
|
+
["set", "@entity.totalFailures", 0],
|
|
708
|
+
healthCheckView("Health Check", "outline")
|
|
346
709
|
]
|
|
347
710
|
},
|
|
348
|
-
// Reset from
|
|
711
|
+
// Reset from Unhealthy
|
|
349
712
|
{
|
|
350
|
-
from:
|
|
713
|
+
from: "Unhealthy",
|
|
351
714
|
to: "Unknown",
|
|
352
715
|
event: "RESET",
|
|
353
716
|
effects: [
|
|
717
|
+
["fetch", "HealthCheckState"],
|
|
354
718
|
["set", "@entity.healthStatus", "unknown"],
|
|
355
719
|
["set", "@entity.consecutiveFailures", 0],
|
|
356
720
|
["set", "@entity.consecutiveSuccesses", 0],
|
|
357
721
|
["set", "@entity.totalChecks", 0],
|
|
358
|
-
["set", "@entity.totalFailures", 0]
|
|
722
|
+
["set", "@entity.totalFailures", 0],
|
|
723
|
+
healthCheckView("Health Check", "outline")
|
|
359
724
|
]
|
|
360
725
|
}
|
|
361
726
|
]
|
|
@@ -363,14 +728,13 @@ var HEALTH_CHECK_BEHAVIOR = {
|
|
|
363
728
|
ticks: [
|
|
364
729
|
{
|
|
365
730
|
name: "periodic_health_check",
|
|
366
|
-
interval:
|
|
367
|
-
effects: [
|
|
368
|
-
description: "Periodically trigger health check"
|
|
731
|
+
interval: 3e4,
|
|
732
|
+
effects: []
|
|
369
733
|
}
|
|
370
734
|
]
|
|
371
735
|
}
|
|
372
736
|
],
|
|
373
|
-
pages: []
|
|
737
|
+
pages: [{ name: "HealthCheckPage", path: "/health-check", isInitial: true, traits: [{ ref: "HealthCheck" }] }]
|
|
374
738
|
}
|
|
375
739
|
]
|
|
376
740
|
};
|
|
@@ -381,6 +745,7 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
381
745
|
orbitals: [
|
|
382
746
|
{
|
|
383
747
|
name: "RateLimiterOrbital",
|
|
748
|
+
theme: INFRA_THEME,
|
|
384
749
|
entity: {
|
|
385
750
|
name: "RateLimiterState",
|
|
386
751
|
persistence: "runtime",
|
|
@@ -398,21 +763,28 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
398
763
|
{
|
|
399
764
|
name: "RateLimiter",
|
|
400
765
|
linkedEntity: "RateLimiterState",
|
|
401
|
-
category: "
|
|
402
|
-
emits: [
|
|
403
|
-
{ event: "RATE_LIMIT_EXCEEDED", scope: "external" }
|
|
404
|
-
],
|
|
766
|
+
category: "interaction",
|
|
405
767
|
stateMachine: {
|
|
406
768
|
states: [
|
|
407
769
|
{ name: "Active", isInitial: true }
|
|
408
770
|
],
|
|
409
771
|
events: [
|
|
772
|
+
{ key: "INIT", name: "Initialize" },
|
|
410
773
|
{ key: "REQUEST", name: "Record Request" },
|
|
411
|
-
{ key: "REQUEST_REJECTED", name: "Request Rejected" },
|
|
412
774
|
{ key: "WINDOW_RESET", name: "Window Reset" },
|
|
413
775
|
{ key: "RESET", name: "Full Reset" }
|
|
414
776
|
],
|
|
415
777
|
transitions: [
|
|
778
|
+
// INIT
|
|
779
|
+
{
|
|
780
|
+
from: "Active",
|
|
781
|
+
to: "Active",
|
|
782
|
+
event: "INIT",
|
|
783
|
+
effects: [
|
|
784
|
+
["fetch", "RateLimiterState"],
|
|
785
|
+
rateLimiterView("Rate Limiter")
|
|
786
|
+
]
|
|
787
|
+
},
|
|
416
788
|
// Request allowed
|
|
417
789
|
{
|
|
418
790
|
from: "Active",
|
|
@@ -420,22 +792,22 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
420
792
|
event: "REQUEST",
|
|
421
793
|
guard: ["<", "@entity.requestCount", "@entity.rateLimit"],
|
|
422
794
|
effects: [
|
|
795
|
+
["fetch", "RateLimiterState"],
|
|
423
796
|
["set", "@entity.requestCount", ["+", "@entity.requestCount", 1]],
|
|
424
|
-
["set", "@entity.totalRequests", ["+", "@entity.totalRequests", 1]]
|
|
797
|
+
["set", "@entity.totalRequests", ["+", "@entity.totalRequests", 1]],
|
|
798
|
+
rateLimiterView("Rate Limiter")
|
|
425
799
|
]
|
|
426
800
|
},
|
|
427
|
-
// Request rejected
|
|
801
|
+
// Request rejected
|
|
428
802
|
{
|
|
429
803
|
from: "Active",
|
|
430
804
|
to: "Active",
|
|
431
805
|
event: "REQUEST",
|
|
432
806
|
guard: [">=", "@entity.requestCount", "@entity.rateLimit"],
|
|
433
807
|
effects: [
|
|
808
|
+
["fetch", "RateLimiterState"],
|
|
434
809
|
["set", "@entity.rejectedRequests", ["+", "@entity.rejectedRequests", 1]],
|
|
435
|
-
|
|
436
|
-
requestCount: "@entity.requestCount",
|
|
437
|
-
rateLimit: "@entity.rateLimit"
|
|
438
|
-
}]
|
|
810
|
+
rateLimiterView("Rate Limiter - Limit Exceeded")
|
|
439
811
|
]
|
|
440
812
|
},
|
|
441
813
|
// Sliding window reset
|
|
@@ -444,8 +816,10 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
444
816
|
to: "Active",
|
|
445
817
|
event: "WINDOW_RESET",
|
|
446
818
|
effects: [
|
|
819
|
+
["fetch", "RateLimiterState"],
|
|
447
820
|
["set", "@entity.requestCount", 0],
|
|
448
|
-
["set", "@entity.windowStart", ["time/now"]]
|
|
821
|
+
["set", "@entity.windowStart", ["time/now"]],
|
|
822
|
+
rateLimiterView("Rate Limiter")
|
|
449
823
|
]
|
|
450
824
|
},
|
|
451
825
|
// Full counter reset
|
|
@@ -454,10 +828,12 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
454
828
|
to: "Active",
|
|
455
829
|
event: "RESET",
|
|
456
830
|
effects: [
|
|
831
|
+
["fetch", "RateLimiterState"],
|
|
457
832
|
["set", "@entity.requestCount", 0],
|
|
458
833
|
["set", "@entity.totalRequests", 0],
|
|
459
834
|
["set", "@entity.rejectedRequests", 0],
|
|
460
|
-
["set", "@entity.windowStart", ["time/now"]]
|
|
835
|
+
["set", "@entity.windowStart", ["time/now"]],
|
|
836
|
+
rateLimiterView("Rate Limiter")
|
|
461
837
|
]
|
|
462
838
|
}
|
|
463
839
|
]
|
|
@@ -465,14 +841,13 @@ var RATE_LIMITER_BEHAVIOR = {
|
|
|
465
841
|
ticks: [
|
|
466
842
|
{
|
|
467
843
|
name: "window_reset",
|
|
468
|
-
interval:
|
|
469
|
-
effects: [
|
|
470
|
-
description: "Reset request counter on sliding window expiry"
|
|
844
|
+
interval: 6e4,
|
|
845
|
+
effects: []
|
|
471
846
|
}
|
|
472
847
|
]
|
|
473
848
|
}
|
|
474
849
|
],
|
|
475
|
-
pages: []
|
|
850
|
+
pages: [{ name: "RateLimiterPage", path: "/rate-limiter", isInitial: true, traits: [{ ref: "RateLimiter" }] }]
|
|
476
851
|
}
|
|
477
852
|
]
|
|
478
853
|
};
|
|
@@ -483,13 +858,14 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
483
858
|
orbitals: [
|
|
484
859
|
{
|
|
485
860
|
name: "CacheAsideOrbital",
|
|
861
|
+
theme: INFRA_THEME,
|
|
486
862
|
entity: {
|
|
487
863
|
name: "CacheEntry",
|
|
488
864
|
persistence: "runtime",
|
|
489
865
|
fields: [
|
|
490
866
|
{ name: "id", type: "string", required: true },
|
|
491
867
|
{ name: "cacheKey", type: "string", default: "" },
|
|
492
|
-
{ name: "cachedValue", type: "
|
|
868
|
+
{ name: "cachedValue", type: "string", default: "" },
|
|
493
869
|
{ name: "cachedAt", type: "number", default: 0 },
|
|
494
870
|
{ name: "ttlMs", type: "number", default: 3e5 },
|
|
495
871
|
{ name: "cacheHits", type: "number", default: 0 },
|
|
@@ -502,12 +878,7 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
502
878
|
{
|
|
503
879
|
name: "CacheAside",
|
|
504
880
|
linkedEntity: "CacheEntry",
|
|
505
|
-
category: "
|
|
506
|
-
emits: [
|
|
507
|
-
{ event: "CACHE_HIT", scope: "internal" },
|
|
508
|
-
{ event: "CACHE_MISS", scope: "internal" },
|
|
509
|
-
{ event: "CACHE_EVICTED", scope: "internal" }
|
|
510
|
-
],
|
|
881
|
+
category: "interaction",
|
|
511
882
|
stateMachine: {
|
|
512
883
|
states: [
|
|
513
884
|
{ name: "Empty", isInitial: true },
|
|
@@ -515,34 +886,50 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
515
886
|
{ name: "Stale" }
|
|
516
887
|
],
|
|
517
888
|
events: [
|
|
889
|
+
{ key: "INIT", name: "Initialize" },
|
|
518
890
|
{ key: "LOOKUP", name: "Cache Lookup" },
|
|
519
|
-
{ key: "POPULATE", name: "Populate Cache"
|
|
891
|
+
{ key: "POPULATE", name: "Populate Cache", payloadSchema: [
|
|
892
|
+
{ name: "value", type: "string", required: true },
|
|
893
|
+
{ name: "key", type: "string", required: true }
|
|
894
|
+
] },
|
|
520
895
|
{ key: "INVALIDATE", name: "Invalidate" },
|
|
521
|
-
{ key: "EVICT", name: "Evict" }
|
|
522
|
-
{ key: "EVICTION_TICK", name: "Eviction Tick" }
|
|
896
|
+
{ key: "EVICT", name: "Evict" }
|
|
523
897
|
],
|
|
524
898
|
transitions: [
|
|
899
|
+
// INIT
|
|
900
|
+
{
|
|
901
|
+
from: "Empty",
|
|
902
|
+
to: "Empty",
|
|
903
|
+
event: "INIT",
|
|
904
|
+
effects: [
|
|
905
|
+
["fetch", "CacheEntry"],
|
|
906
|
+
cacheEmptyView("Cache")
|
|
907
|
+
]
|
|
908
|
+
},
|
|
525
909
|
// Empty: lookup is a miss
|
|
526
910
|
{
|
|
527
911
|
from: "Empty",
|
|
528
912
|
to: "Empty",
|
|
529
913
|
event: "LOOKUP",
|
|
530
914
|
effects: [
|
|
915
|
+
["fetch", "CacheEntry"],
|
|
531
916
|
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
532
917
|
["set", "@entity.lastAccessed", ["time/now"]],
|
|
533
|
-
|
|
918
|
+
cacheEmptyView("Cache - Miss")
|
|
534
919
|
]
|
|
535
920
|
},
|
|
536
|
-
// Empty
|
|
921
|
+
// Empty -> Fresh: populate after fetch
|
|
537
922
|
{
|
|
538
923
|
from: "Empty",
|
|
539
924
|
to: "Fresh",
|
|
540
925
|
event: "POPULATE",
|
|
541
926
|
effects: [
|
|
927
|
+
["fetch", "CacheEntry"],
|
|
542
928
|
["set", "@entity.cachedValue", "@payload.value"],
|
|
543
929
|
["set", "@entity.cacheKey", "@payload.key"],
|
|
544
930
|
["set", "@entity.cachedAt", ["time/now"]],
|
|
545
|
-
["set", "@entity.isFresh", true]
|
|
931
|
+
["set", "@entity.isFresh", true],
|
|
932
|
+
cacheStatsView("Cache - Fresh")
|
|
546
933
|
]
|
|
547
934
|
},
|
|
548
935
|
// Fresh: lookup is a hit
|
|
@@ -552,22 +939,36 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
552
939
|
event: "LOOKUP",
|
|
553
940
|
guard: ["<", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
|
|
554
941
|
effects: [
|
|
942
|
+
["fetch", "CacheEntry"],
|
|
555
943
|
["set", "@entity.cacheHits", ["+", "@entity.cacheHits", 1]],
|
|
556
944
|
["set", "@entity.lastAccessed", ["time/now"]],
|
|
557
|
-
|
|
945
|
+
cacheStatsView("Cache - Hit")
|
|
558
946
|
]
|
|
559
947
|
},
|
|
560
|
-
// Fresh
|
|
948
|
+
// Fresh -> Stale: TTL expired on lookup
|
|
561
949
|
{
|
|
562
950
|
from: "Fresh",
|
|
563
951
|
to: "Stale",
|
|
564
952
|
event: "LOOKUP",
|
|
565
953
|
guard: [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"],
|
|
566
954
|
effects: [
|
|
955
|
+
["fetch", "CacheEntry"],
|
|
567
956
|
["set", "@entity.isFresh", false],
|
|
568
957
|
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
569
958
|
["set", "@entity.lastAccessed", ["time/now"]],
|
|
570
|
-
|
|
959
|
+
cacheStatsView("Cache - Stale")
|
|
960
|
+
]
|
|
961
|
+
},
|
|
962
|
+
// Fresh -> Fresh: update cache
|
|
963
|
+
{
|
|
964
|
+
from: "Fresh",
|
|
965
|
+
to: "Fresh",
|
|
966
|
+
event: "POPULATE",
|
|
967
|
+
effects: [
|
|
968
|
+
["fetch", "CacheEntry"],
|
|
969
|
+
["set", "@entity.cachedValue", "@payload.value"],
|
|
970
|
+
["set", "@entity.cachedAt", ["time/now"]],
|
|
971
|
+
cacheStatsView("Cache - Fresh")
|
|
571
972
|
]
|
|
572
973
|
},
|
|
573
974
|
// Stale: lookup is a miss
|
|
@@ -576,65 +977,75 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
576
977
|
to: "Stale",
|
|
577
978
|
event: "LOOKUP",
|
|
578
979
|
effects: [
|
|
980
|
+
["fetch", "CacheEntry"],
|
|
579
981
|
["set", "@entity.cacheMisses", ["+", "@entity.cacheMisses", 1]],
|
|
580
982
|
["set", "@entity.lastAccessed", ["time/now"]],
|
|
581
|
-
|
|
983
|
+
cacheStatsView("Cache - Stale")
|
|
582
984
|
]
|
|
583
985
|
},
|
|
584
|
-
// Stale
|
|
986
|
+
// Stale -> Fresh: re-populate
|
|
585
987
|
{
|
|
586
988
|
from: "Stale",
|
|
587
989
|
to: "Fresh",
|
|
588
990
|
event: "POPULATE",
|
|
589
991
|
effects: [
|
|
992
|
+
["fetch", "CacheEntry"],
|
|
590
993
|
["set", "@entity.cachedValue", "@payload.value"],
|
|
591
994
|
["set", "@entity.cachedAt", ["time/now"]],
|
|
592
|
-
["set", "@entity.isFresh", true]
|
|
995
|
+
["set", "@entity.isFresh", true],
|
|
996
|
+
cacheStatsView("Cache - Fresh")
|
|
593
997
|
]
|
|
594
998
|
},
|
|
595
|
-
//
|
|
999
|
+
// Invalidate from Fresh
|
|
596
1000
|
{
|
|
597
1001
|
from: "Fresh",
|
|
598
|
-
to: "
|
|
599
|
-
event: "
|
|
1002
|
+
to: "Empty",
|
|
1003
|
+
event: "INVALIDATE",
|
|
600
1004
|
effects: [
|
|
601
|
-
["
|
|
602
|
-
["set", "@entity.
|
|
1005
|
+
["fetch", "CacheEntry"],
|
|
1006
|
+
["set", "@entity.cachedValue", ""],
|
|
1007
|
+
["set", "@entity.isFresh", false],
|
|
1008
|
+
["set", "@entity.cachedAt", 0],
|
|
1009
|
+
cacheEmptyView("Cache")
|
|
603
1010
|
]
|
|
604
1011
|
},
|
|
605
|
-
// Invalidate from
|
|
1012
|
+
// Invalidate from Stale
|
|
606
1013
|
{
|
|
607
|
-
from:
|
|
1014
|
+
from: "Stale",
|
|
608
1015
|
to: "Empty",
|
|
609
1016
|
event: "INVALIDATE",
|
|
610
1017
|
effects: [
|
|
611
|
-
["
|
|
1018
|
+
["fetch", "CacheEntry"],
|
|
1019
|
+
["set", "@entity.cachedValue", ""],
|
|
612
1020
|
["set", "@entity.isFresh", false],
|
|
613
|
-
["set", "@entity.cachedAt", 0]
|
|
1021
|
+
["set", "@entity.cachedAt", 0],
|
|
1022
|
+
cacheEmptyView("Cache")
|
|
614
1023
|
]
|
|
615
1024
|
},
|
|
616
|
-
// Evict
|
|
1025
|
+
// Evict from Fresh
|
|
617
1026
|
{
|
|
618
|
-
from:
|
|
1027
|
+
from: "Fresh",
|
|
619
1028
|
to: "Empty",
|
|
620
1029
|
event: "EVICT",
|
|
621
1030
|
effects: [
|
|
622
|
-
["
|
|
1031
|
+
["fetch", "CacheEntry"],
|
|
1032
|
+
["set", "@entity.cachedValue", ""],
|
|
623
1033
|
["set", "@entity.isFresh", false],
|
|
624
1034
|
["set", "@entity.cachedAt", 0],
|
|
625
|
-
|
|
1035
|
+
cacheEmptyView("Cache")
|
|
626
1036
|
]
|
|
627
1037
|
},
|
|
628
|
-
//
|
|
1038
|
+
// Evict from Stale
|
|
629
1039
|
{
|
|
630
1040
|
from: "Stale",
|
|
631
1041
|
to: "Empty",
|
|
632
|
-
event: "
|
|
1042
|
+
event: "EVICT",
|
|
633
1043
|
effects: [
|
|
634
|
-
["
|
|
1044
|
+
["fetch", "CacheEntry"],
|
|
1045
|
+
["set", "@entity.cachedValue", ""],
|
|
635
1046
|
["set", "@entity.isFresh", false],
|
|
636
1047
|
["set", "@entity.cachedAt", 0],
|
|
637
|
-
|
|
1048
|
+
cacheEmptyView("Cache")
|
|
638
1049
|
]
|
|
639
1050
|
}
|
|
640
1051
|
]
|
|
@@ -642,15 +1053,14 @@ var CACHE_ASIDE_BEHAVIOR = {
|
|
|
642
1053
|
ticks: [
|
|
643
1054
|
{
|
|
644
1055
|
name: "eviction_sweep",
|
|
645
|
-
interval:
|
|
1056
|
+
interval: 6e4,
|
|
646
1057
|
guard: ["and", ["!=", "@entity.cachedAt", 0], [">=", ["-", ["time/now"], "@entity.cachedAt"], "@entity.ttlMs"]],
|
|
647
|
-
effects: [
|
|
648
|
-
description: "Periodically evict stale cache entries"
|
|
1058
|
+
effects: []
|
|
649
1059
|
}
|
|
650
1060
|
]
|
|
651
1061
|
}
|
|
652
1062
|
],
|
|
653
|
-
pages: []
|
|
1063
|
+
pages: [{ name: "CachePage", path: "/cache", isInitial: true, traits: [{ ref: "CacheAside" }] }]
|
|
654
1064
|
}
|
|
655
1065
|
]
|
|
656
1066
|
};
|
|
@@ -661,6 +1071,7 @@ var SAGA_BEHAVIOR = {
|
|
|
661
1071
|
orbitals: [
|
|
662
1072
|
{
|
|
663
1073
|
name: "SagaOrbital",
|
|
1074
|
+
theme: INFRA_THEME,
|
|
664
1075
|
entity: {
|
|
665
1076
|
name: "SagaState",
|
|
666
1077
|
persistence: "runtime",
|
|
@@ -670,8 +1081,6 @@ var SAGA_BEHAVIOR = {
|
|
|
670
1081
|
{ name: "currentStep", type: "number", default: 0 },
|
|
671
1082
|
{ name: "totalSteps", type: "number", default: 0 },
|
|
672
1083
|
{ name: "sagaStatus", type: "string", default: "idle" },
|
|
673
|
-
{ name: "completedSteps", type: "array", default: [] },
|
|
674
|
-
{ name: "compensatedSteps", type: "array", default: [] },
|
|
675
1084
|
{ name: "failedStep", type: "number", default: -1 },
|
|
676
1085
|
{ name: "failureReason", type: "string", default: "" },
|
|
677
1086
|
{ name: "startedAt", type: "number", default: 0 },
|
|
@@ -682,15 +1091,7 @@ var SAGA_BEHAVIOR = {
|
|
|
682
1091
|
{
|
|
683
1092
|
name: "Saga",
|
|
684
1093
|
linkedEntity: "SagaState",
|
|
685
|
-
category: "
|
|
686
|
-
emits: [
|
|
687
|
-
{ event: "SAGA_STARTED", scope: "external" },
|
|
688
|
-
{ event: "SAGA_STEP_COMPLETED", scope: "external" },
|
|
689
|
-
{ event: "SAGA_COMPLETED", scope: "external" },
|
|
690
|
-
{ event: "SAGA_COMPENSATING", scope: "external" },
|
|
691
|
-
{ event: "SAGA_COMPENSATION_DONE", scope: "external" },
|
|
692
|
-
{ event: "SAGA_FAILED", scope: "external" }
|
|
693
|
-
],
|
|
1094
|
+
category: "interaction",
|
|
694
1095
|
stateMachine: {
|
|
695
1096
|
states: [
|
|
696
1097
|
{ name: "Idle", isInitial: true },
|
|
@@ -700,6 +1101,7 @@ var SAGA_BEHAVIOR = {
|
|
|
700
1101
|
{ name: "Failed" }
|
|
701
1102
|
],
|
|
702
1103
|
events: [
|
|
1104
|
+
{ key: "INIT", name: "Initialize" },
|
|
703
1105
|
{ key: "START_SAGA", name: "Start Saga" },
|
|
704
1106
|
{ key: "STEP_SUCCESS", name: "Step Success" },
|
|
705
1107
|
{ key: "STEP_FAILURE", name: "Step Failure" },
|
|
@@ -708,20 +1110,29 @@ var SAGA_BEHAVIOR = {
|
|
|
708
1110
|
{ key: "RESET", name: "Reset" }
|
|
709
1111
|
],
|
|
710
1112
|
transitions: [
|
|
711
|
-
//
|
|
1113
|
+
// INIT
|
|
1114
|
+
{
|
|
1115
|
+
from: "Idle",
|
|
1116
|
+
to: "Idle",
|
|
1117
|
+
event: "INIT",
|
|
1118
|
+
effects: [
|
|
1119
|
+
["fetch", "SagaState"],
|
|
1120
|
+
sagaView("Saga")
|
|
1121
|
+
]
|
|
1122
|
+
},
|
|
1123
|
+
// Idle -> Running: start the saga
|
|
712
1124
|
{
|
|
713
1125
|
from: "Idle",
|
|
714
1126
|
to: "Running",
|
|
715
1127
|
event: "START_SAGA",
|
|
716
1128
|
effects: [
|
|
1129
|
+
["fetch", "SagaState"],
|
|
717
1130
|
["set", "@entity.sagaStatus", "running"],
|
|
718
1131
|
["set", "@entity.currentStep", 0],
|
|
719
|
-
["set", "@entity.completedSteps", []],
|
|
720
|
-
["set", "@entity.compensatedSteps", []],
|
|
721
1132
|
["set", "@entity.failedStep", -1],
|
|
722
1133
|
["set", "@entity.failureReason", ""],
|
|
723
1134
|
["set", "@entity.startedAt", ["time/now"]],
|
|
724
|
-
|
|
1135
|
+
sagaView("Saga - Running")
|
|
725
1136
|
]
|
|
726
1137
|
},
|
|
727
1138
|
// Running: step success, more steps remaining
|
|
@@ -731,37 +1142,34 @@ var SAGA_BEHAVIOR = {
|
|
|
731
1142
|
event: "STEP_SUCCESS",
|
|
732
1143
|
guard: ["<", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
|
|
733
1144
|
effects: [
|
|
1145
|
+
["fetch", "SagaState"],
|
|
734
1146
|
["set", "@entity.currentStep", ["+", "@entity.currentStep", 1]],
|
|
735
|
-
|
|
736
|
-
step: "@entity.currentStep",
|
|
737
|
-
totalSteps: "@entity.totalSteps"
|
|
738
|
-
}]
|
|
1147
|
+
sagaView("Saga - Running")
|
|
739
1148
|
]
|
|
740
1149
|
},
|
|
741
|
-
// Running
|
|
1150
|
+
// Running -> Completed: last step succeeded
|
|
742
1151
|
{
|
|
743
1152
|
from: "Running",
|
|
744
1153
|
to: "Completed",
|
|
745
1154
|
event: "STEP_SUCCESS",
|
|
746
1155
|
guard: [">=", ["+", "@entity.currentStep", 1], "@entity.totalSteps"],
|
|
747
1156
|
effects: [
|
|
1157
|
+
["fetch", "SagaState"],
|
|
748
1158
|
["set", "@entity.sagaStatus", "completed"],
|
|
749
1159
|
["set", "@entity.completedAt", ["time/now"]],
|
|
750
|
-
|
|
1160
|
+
sagaView("Saga - Completed")
|
|
751
1161
|
]
|
|
752
1162
|
},
|
|
753
|
-
// Running
|
|
1163
|
+
// Running -> Compensating: a step failed
|
|
754
1164
|
{
|
|
755
1165
|
from: "Running",
|
|
756
1166
|
to: "Compensating",
|
|
757
1167
|
event: "STEP_FAILURE",
|
|
758
1168
|
effects: [
|
|
1169
|
+
["fetch", "SagaState"],
|
|
759
1170
|
["set", "@entity.sagaStatus", "compensating"],
|
|
760
1171
|
["set", "@entity.failedStep", "@entity.currentStep"],
|
|
761
|
-
|
|
762
|
-
failedStep: "@entity.currentStep",
|
|
763
|
-
sagaName: "@entity.sagaName"
|
|
764
|
-
}]
|
|
1172
|
+
sagaView("Saga - Compensating")
|
|
765
1173
|
]
|
|
766
1174
|
},
|
|
767
1175
|
// Compensating: compensation step succeeded, more to undo
|
|
@@ -771,47 +1179,62 @@ var SAGA_BEHAVIOR = {
|
|
|
771
1179
|
event: "COMPENSATE_SUCCESS",
|
|
772
1180
|
guard: [">", "@entity.currentStep", 0],
|
|
773
1181
|
effects: [
|
|
774
|
-
["
|
|
1182
|
+
["fetch", "SagaState"],
|
|
1183
|
+
["set", "@entity.currentStep", ["-", "@entity.currentStep", 1]],
|
|
1184
|
+
sagaView("Saga - Compensating")
|
|
775
1185
|
]
|
|
776
1186
|
},
|
|
777
|
-
// Compensating
|
|
1187
|
+
// Compensating -> Failed: all compensations done (reached step 0)
|
|
778
1188
|
{
|
|
779
1189
|
from: "Compensating",
|
|
780
1190
|
to: "Failed",
|
|
781
1191
|
event: "COMPENSATE_SUCCESS",
|
|
782
1192
|
guard: ["<=", "@entity.currentStep", 0],
|
|
783
1193
|
effects: [
|
|
1194
|
+
["fetch", "SagaState"],
|
|
784
1195
|
["set", "@entity.sagaStatus", "failed"],
|
|
785
1196
|
["set", "@entity.completedAt", ["time/now"]],
|
|
786
|
-
|
|
1197
|
+
sagaView("Saga - Failed")
|
|
787
1198
|
]
|
|
788
1199
|
},
|
|
789
|
-
// Compensating
|
|
1200
|
+
// Compensating -> Failed: compensation itself failed
|
|
790
1201
|
{
|
|
791
1202
|
from: "Compensating",
|
|
792
1203
|
to: "Failed",
|
|
793
1204
|
event: "COMPENSATE_FAILURE",
|
|
794
1205
|
effects: [
|
|
1206
|
+
["fetch", "SagaState"],
|
|
795
1207
|
["set", "@entity.sagaStatus", "failed"],
|
|
796
1208
|
["set", "@entity.completedAt", ["time/now"]],
|
|
797
|
-
|
|
798
|
-
sagaName: "@entity.sagaName",
|
|
799
|
-
reason: "Compensation failed"
|
|
800
|
-
}]
|
|
1209
|
+
sagaView("Saga - Failed")
|
|
801
1210
|
]
|
|
802
1211
|
},
|
|
803
|
-
// Reset from
|
|
1212
|
+
// Reset from Completed
|
|
804
1213
|
{
|
|
805
|
-
from:
|
|
1214
|
+
from: "Completed",
|
|
806
1215
|
to: "Idle",
|
|
807
1216
|
event: "RESET",
|
|
808
1217
|
effects: [
|
|
1218
|
+
["fetch", "SagaState"],
|
|
809
1219
|
["set", "@entity.sagaStatus", "idle"],
|
|
810
1220
|
["set", "@entity.currentStep", 0],
|
|
811
|
-
["set", "@entity.completedSteps", []],
|
|
812
|
-
["set", "@entity.compensatedSteps", []],
|
|
813
1221
|
["set", "@entity.failedStep", -1],
|
|
814
|
-
["set", "@entity.failureReason", ""]
|
|
1222
|
+
["set", "@entity.failureReason", ""],
|
|
1223
|
+
sagaView("Saga")
|
|
1224
|
+
]
|
|
1225
|
+
},
|
|
1226
|
+
// Reset from Failed
|
|
1227
|
+
{
|
|
1228
|
+
from: "Failed",
|
|
1229
|
+
to: "Idle",
|
|
1230
|
+
event: "RESET",
|
|
1231
|
+
effects: [
|
|
1232
|
+
["fetch", "SagaState"],
|
|
1233
|
+
["set", "@entity.sagaStatus", "idle"],
|
|
1234
|
+
["set", "@entity.currentStep", 0],
|
|
1235
|
+
["set", "@entity.failedStep", -1],
|
|
1236
|
+
["set", "@entity.failureReason", ""],
|
|
1237
|
+
sagaView("Saga")
|
|
815
1238
|
]
|
|
816
1239
|
}
|
|
817
1240
|
]
|
|
@@ -819,7 +1242,7 @@ var SAGA_BEHAVIOR = {
|
|
|
819
1242
|
ticks: []
|
|
820
1243
|
}
|
|
821
1244
|
],
|
|
822
|
-
pages: []
|
|
1245
|
+
pages: [{ name: "SagaPage", path: "/saga", isInitial: true, traits: [{ ref: "Saga" }] }]
|
|
823
1246
|
}
|
|
824
1247
|
]
|
|
825
1248
|
};
|
|
@@ -830,15 +1253,13 @@ var METRICS_COLLECTOR_BEHAVIOR = {
|
|
|
830
1253
|
orbitals: [
|
|
831
1254
|
{
|
|
832
1255
|
name: "MetricsCollectorOrbital",
|
|
1256
|
+
theme: INFRA_THEME,
|
|
833
1257
|
entity: {
|
|
834
1258
|
name: "MetricsState",
|
|
835
1259
|
persistence: "runtime",
|
|
836
1260
|
fields: [
|
|
837
1261
|
{ name: "id", type: "string", required: true },
|
|
838
|
-
{ name: "counters", type: "object", default: {} },
|
|
839
|
-
{ name: "gauges", type: "object", default: {} },
|
|
840
1262
|
{ name: "lastFlush", type: "number", default: 0 },
|
|
841
|
-
{ name: "flushIntervalMs", type: "number", default: 6e4 },
|
|
842
1263
|
{ name: "totalFlushes", type: "number", default: 0 },
|
|
843
1264
|
{ name: "totalRecorded", type: "number", default: 0 }
|
|
844
1265
|
]
|
|
@@ -847,28 +1268,38 @@ var METRICS_COLLECTOR_BEHAVIOR = {
|
|
|
847
1268
|
{
|
|
848
1269
|
name: "MetricsCollector",
|
|
849
1270
|
linkedEntity: "MetricsState",
|
|
850
|
-
category: "
|
|
851
|
-
emits: [
|
|
852
|
-
{ event: "METRICS_REPORT", scope: "external" }
|
|
853
|
-
],
|
|
1271
|
+
category: "interaction",
|
|
854
1272
|
stateMachine: {
|
|
855
1273
|
states: [
|
|
856
1274
|
{ name: "Collecting", isInitial: true }
|
|
857
1275
|
],
|
|
858
1276
|
events: [
|
|
1277
|
+
{ key: "INIT", name: "Initialize" },
|
|
859
1278
|
{ key: "RECORD_COUNTER", name: "Record Counter" },
|
|
860
1279
|
{ key: "RECORD_GAUGE", name: "Record Gauge" },
|
|
861
1280
|
{ key: "FLUSH", name: "Flush Metrics" },
|
|
862
1281
|
{ key: "RESET", name: "Reset All" }
|
|
863
1282
|
],
|
|
864
1283
|
transitions: [
|
|
1284
|
+
// INIT
|
|
1285
|
+
{
|
|
1286
|
+
from: "Collecting",
|
|
1287
|
+
to: "Collecting",
|
|
1288
|
+
event: "INIT",
|
|
1289
|
+
effects: [
|
|
1290
|
+
["fetch", "MetricsState"],
|
|
1291
|
+
metricsView("Metrics Collector")
|
|
1292
|
+
]
|
|
1293
|
+
},
|
|
865
1294
|
// Record a counter increment
|
|
866
1295
|
{
|
|
867
1296
|
from: "Collecting",
|
|
868
1297
|
to: "Collecting",
|
|
869
1298
|
event: "RECORD_COUNTER",
|
|
870
1299
|
effects: [
|
|
871
|
-
["
|
|
1300
|
+
["fetch", "MetricsState"],
|
|
1301
|
+
["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]],
|
|
1302
|
+
metricsView("Metrics Collector")
|
|
872
1303
|
]
|
|
873
1304
|
},
|
|
874
1305
|
// Record a gauge value
|
|
@@ -877,23 +1308,21 @@ var METRICS_COLLECTOR_BEHAVIOR = {
|
|
|
877
1308
|
to: "Collecting",
|
|
878
1309
|
event: "RECORD_GAUGE",
|
|
879
1310
|
effects: [
|
|
880
|
-
["
|
|
1311
|
+
["fetch", "MetricsState"],
|
|
1312
|
+
["set", "@entity.totalRecorded", ["+", "@entity.totalRecorded", 1]],
|
|
1313
|
+
metricsView("Metrics Collector")
|
|
881
1314
|
]
|
|
882
1315
|
},
|
|
883
|
-
// Flush:
|
|
1316
|
+
// Flush: reset counters
|
|
884
1317
|
{
|
|
885
1318
|
from: "Collecting",
|
|
886
1319
|
to: "Collecting",
|
|
887
1320
|
event: "FLUSH",
|
|
888
1321
|
effects: [
|
|
889
|
-
["
|
|
890
|
-
counters: "@entity.counters",
|
|
891
|
-
gauges: "@entity.gauges",
|
|
892
|
-
totalRecorded: "@entity.totalRecorded"
|
|
893
|
-
}],
|
|
894
|
-
["set", "@entity.counters", {}],
|
|
1322
|
+
["fetch", "MetricsState"],
|
|
895
1323
|
["set", "@entity.lastFlush", ["time/now"]],
|
|
896
|
-
["set", "@entity.totalFlushes", ["+", "@entity.totalFlushes", 1]]
|
|
1324
|
+
["set", "@entity.totalFlushes", ["+", "@entity.totalFlushes", 1]],
|
|
1325
|
+
metricsView("Metrics Collector")
|
|
897
1326
|
]
|
|
898
1327
|
},
|
|
899
1328
|
// Full reset
|
|
@@ -902,11 +1331,11 @@ var METRICS_COLLECTOR_BEHAVIOR = {
|
|
|
902
1331
|
to: "Collecting",
|
|
903
1332
|
event: "RESET",
|
|
904
1333
|
effects: [
|
|
905
|
-
["
|
|
906
|
-
["set", "@entity.gauges", {}],
|
|
1334
|
+
["fetch", "MetricsState"],
|
|
907
1335
|
["set", "@entity.totalRecorded", 0],
|
|
908
1336
|
["set", "@entity.totalFlushes", 0],
|
|
909
|
-
["set", "@entity.lastFlush", 0]
|
|
1337
|
+
["set", "@entity.lastFlush", 0],
|
|
1338
|
+
metricsView("Metrics Collector")
|
|
910
1339
|
]
|
|
911
1340
|
}
|
|
912
1341
|
]
|
|
@@ -914,15 +1343,14 @@ var METRICS_COLLECTOR_BEHAVIOR = {
|
|
|
914
1343
|
ticks: [
|
|
915
1344
|
{
|
|
916
1345
|
name: "periodic_flush",
|
|
917
|
-
interval:
|
|
1346
|
+
interval: 6e4,
|
|
918
1347
|
guard: [">", "@entity.totalRecorded", 0],
|
|
919
|
-
effects: [
|
|
920
|
-
description: "Periodically flush accumulated metrics"
|
|
1348
|
+
effects: []
|
|
921
1349
|
}
|
|
922
1350
|
]
|
|
923
1351
|
}
|
|
924
1352
|
],
|
|
925
|
-
pages: []
|
|
1353
|
+
pages: [{ name: "MetricsPage", path: "/metrics", isInitial: true, traits: [{ ref: "MetricsCollector" }] }]
|
|
926
1354
|
}
|
|
927
1355
|
]
|
|
928
1356
|
};
|