deepline 0.3.16 → 0.3.18
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/bundling-sources/sdk/src/client.ts +7 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/integrations/bettercontact-execution-policy.ts +29 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +45 -0
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +19 -3
- package/dist/bundling-sources/shared_libs/play-runtime/bettercontact-batching.ts +726 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +45 -24
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +254 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-batching-registry.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +6 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +28 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +5 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +344 -26
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +50 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +378 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-reliability-policy.ts +391 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-traffic-policy.ts +125 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +36 -39
- package/dist/cli/index.js +265 -1
- package/dist/cli/index.mjs +265 -1
- package/dist/index.js +265 -1
- package/dist/index.mjs +265 -1
- package/dist/install-integrity.json +6 -0
- package/package.json +1 -1
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical incident-drill catalog for the Play Runtime.
|
|
3
|
+
*
|
|
4
|
+
* A drill is not a retry policy and it never changes a Play by itself. It
|
|
5
|
+
* states a bounded fault we can deliberately exercise, the topology where it
|
|
6
|
+
* is meaningful, and the durable safety facts an observer must verify. Test
|
|
7
|
+
* seams, the local admin CLI, V2 scenarios, and documentation are Adapters to
|
|
8
|
+
* this Module; they must not invent their own outcome descriptions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export const RUNTIME_TEST_FAULT_IDS = [
|
|
12
|
+
'receipt_complete_write_fail',
|
|
13
|
+
'receipt_fail_write_fail',
|
|
14
|
+
'worker_receipt_complete_write_fail',
|
|
15
|
+
'invocation_response_delivery_abort',
|
|
16
|
+
'receipt_gateway_hold_ms',
|
|
17
|
+
'receipt_claim_query_hold_once_ms',
|
|
18
|
+
'receipt_claim_response_timeout',
|
|
19
|
+
'modal_sandbox_create_resource_exhausted',
|
|
20
|
+
'runtime_sheet_page_tail_hold_ms',
|
|
21
|
+
] as const;
|
|
22
|
+
|
|
23
|
+
export type RuntimeTestFaultName = (typeof RUNTIME_TEST_FAULT_IDS)[number];
|
|
24
|
+
|
|
25
|
+
export type RuntimeIncidentDrillId =
|
|
26
|
+
| 'local_worker_process_outage'
|
|
27
|
+
| 'local_gateway_process_outage'
|
|
28
|
+
| 'local_runtime_process_outage'
|
|
29
|
+
| RuntimeTestFaultName;
|
|
30
|
+
|
|
31
|
+
export type RuntimeIncidentTopology =
|
|
32
|
+
| 'local_daytona'
|
|
33
|
+
| 'preview_fly'
|
|
34
|
+
| 'preview_direct_modal';
|
|
35
|
+
|
|
36
|
+
export type RuntimeIncidentSafetyFact =
|
|
37
|
+
| 'same_logical_run'
|
|
38
|
+
| 'no_false_success'
|
|
39
|
+
| 'bounded_provider_execution'
|
|
40
|
+
| 'retry_or_explicit_recovery'
|
|
41
|
+
| 'no_user_code_before_recovery'
|
|
42
|
+
| 'all_rows_settle_once';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The automated evidence that proves this drill. A focused regression owns a
|
|
46
|
+
* narrow storage/protocol invariant; a black-box scenario drives the full
|
|
47
|
+
* local (or Preview) runtime. Keeping this on the catalog means on-call and
|
|
48
|
+
* CI see the same answer to “how do we prove this?” as the injector.
|
|
49
|
+
*/
|
|
50
|
+
export type RuntimeIncidentVerification = Readonly<{
|
|
51
|
+
kind: 'focused_regression' | 'local_black_box' | 'preview_black_box';
|
|
52
|
+
target: string;
|
|
53
|
+
}>;
|
|
54
|
+
|
|
55
|
+
export type RuntimeIncidentDrill = Readonly<{
|
|
56
|
+
id: RuntimeIncidentDrillId;
|
|
57
|
+
description: string;
|
|
58
|
+
topologies: readonly RuntimeIncidentTopology[];
|
|
59
|
+
control:
|
|
60
|
+
| Readonly<{
|
|
61
|
+
kind: 'process';
|
|
62
|
+
component: 'worker' | 'gateway' | 'all';
|
|
63
|
+
modes: readonly ('pause' | 'crash')[];
|
|
64
|
+
}>
|
|
65
|
+
| Readonly<{
|
|
66
|
+
kind: 'runtime_test_fault';
|
|
67
|
+
defaultValue: number;
|
|
68
|
+
valueMeaning: 'occurrence' | 'milliseconds';
|
|
69
|
+
}>;
|
|
70
|
+
expected: Readonly<{
|
|
71
|
+
outcome: string;
|
|
72
|
+
safetyFacts: readonly RuntimeIncidentSafetyFact[];
|
|
73
|
+
}>;
|
|
74
|
+
verification: RuntimeIncidentVerification;
|
|
75
|
+
}>;
|
|
76
|
+
|
|
77
|
+
const LOCAL_TOPOLOGY = ['local_daytona'] as const;
|
|
78
|
+
const LOCAL_AND_PREVIEW_TOPOLOGIES = [
|
|
79
|
+
'local_daytona',
|
|
80
|
+
'preview_fly',
|
|
81
|
+
'preview_direct_modal',
|
|
82
|
+
] as const;
|
|
83
|
+
const MODAL_PREVIEW_TOPOLOGY = ['preview_direct_modal'] as const;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* The single catalog that binds an injected fault to its required proof.
|
|
87
|
+
*
|
|
88
|
+
* `valueMeaning` is deliberately explicit: callers cannot accidentally pass
|
|
89
|
+
* a millisecond delay where the runtime interprets an occurrence count.
|
|
90
|
+
*/
|
|
91
|
+
export const RUNTIME_INCIDENT_DRILL_CATALOG: readonly RuntimeIncidentDrill[] = [
|
|
92
|
+
{
|
|
93
|
+
id: 'local_worker_process_outage',
|
|
94
|
+
description:
|
|
95
|
+
'Interrupt the scheduler worker in the selected non-production runtime topology.',
|
|
96
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
97
|
+
control: {
|
|
98
|
+
kind: 'process',
|
|
99
|
+
component: 'worker',
|
|
100
|
+
modes: ['pause', 'crash'],
|
|
101
|
+
},
|
|
102
|
+
expected: {
|
|
103
|
+
outcome:
|
|
104
|
+
'The same logical run stays durable through the worker outage and completes after the selected topology recovers.',
|
|
105
|
+
safetyFacts: ['same_logical_run', 'no_false_success'],
|
|
106
|
+
},
|
|
107
|
+
verification: {
|
|
108
|
+
kind: 'local_black_box',
|
|
109
|
+
target: 'local-component-outage-recovery-e2e',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
id: 'local_gateway_process_outage',
|
|
114
|
+
description:
|
|
115
|
+
'Interrupt the receipt gateway in the selected non-production runtime topology.',
|
|
116
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
117
|
+
control: {
|
|
118
|
+
kind: 'process',
|
|
119
|
+
component: 'gateway',
|
|
120
|
+
modes: ['pause', 'crash'],
|
|
121
|
+
},
|
|
122
|
+
expected: {
|
|
123
|
+
outcome:
|
|
124
|
+
'In-flight work recovers only at a safe receipt boundary and the same logical run completes after the gateway recovers.',
|
|
125
|
+
safetyFacts: [
|
|
126
|
+
'same_logical_run',
|
|
127
|
+
'no_false_success',
|
|
128
|
+
'bounded_provider_execution',
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
verification: {
|
|
132
|
+
kind: 'local_black_box',
|
|
133
|
+
target: 'local-component-outage-recovery-e2e',
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: 'local_runtime_process_outage',
|
|
138
|
+
description:
|
|
139
|
+
'Interrupt both runtime components in the selected non-production topology.',
|
|
140
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
141
|
+
control: { kind: 'process', component: 'all', modes: ['pause', 'crash'] },
|
|
142
|
+
expected: {
|
|
143
|
+
outcome:
|
|
144
|
+
'Durable work waits through the combined outage; it never becomes a false success or creates a second logical run.',
|
|
145
|
+
safetyFacts: ['same_logical_run', 'no_false_success'],
|
|
146
|
+
},
|
|
147
|
+
verification: {
|
|
148
|
+
kind: 'local_black_box',
|
|
149
|
+
target: 'local-component-outage-recovery-e2e',
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
id: 'receipt_complete_write_fail',
|
|
154
|
+
description: 'Fail the next durable receipt-completion write.',
|
|
155
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
156
|
+
control: {
|
|
157
|
+
kind: 'runtime_test_fault',
|
|
158
|
+
defaultValue: 1,
|
|
159
|
+
valueMeaning: 'occurrence',
|
|
160
|
+
},
|
|
161
|
+
expected: {
|
|
162
|
+
outcome:
|
|
163
|
+
'The failed run is loud, and a later bounded recovery may repeat the affected provider operation if its prior completion was not durable.',
|
|
164
|
+
safetyFacts: ['retry_or_explicit_recovery', 'bounded_provider_execution'],
|
|
165
|
+
},
|
|
166
|
+
verification: {
|
|
167
|
+
kind: 'local_black_box',
|
|
168
|
+
target: 'receipt-persist-failure-run-fatal-e2e',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'receipt_fail_write_fail',
|
|
173
|
+
description: 'Fail the next durable receipt-failure write.',
|
|
174
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
175
|
+
control: {
|
|
176
|
+
kind: 'runtime_test_fault',
|
|
177
|
+
defaultValue: 1,
|
|
178
|
+
valueMeaning: 'occurrence',
|
|
179
|
+
},
|
|
180
|
+
expected: {
|
|
181
|
+
outcome:
|
|
182
|
+
'The failure is loud; recovery remains bounded and may repeat an operation whose prior outcome was not durably recorded.',
|
|
183
|
+
safetyFacts: ['retry_or_explicit_recovery', 'bounded_provider_execution'],
|
|
184
|
+
},
|
|
185
|
+
verification: {
|
|
186
|
+
kind: 'focused_regression',
|
|
187
|
+
target: 'tests/lib/plays/runtime-test-fault-registry.test.ts',
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
id: 'worker_receipt_complete_write_fail',
|
|
192
|
+
description: 'Fail the worker-side receipt-completion write once.',
|
|
193
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
194
|
+
control: {
|
|
195
|
+
kind: 'runtime_test_fault',
|
|
196
|
+
defaultValue: 1,
|
|
197
|
+
valueMeaning: 'occurrence',
|
|
198
|
+
},
|
|
199
|
+
expected: {
|
|
200
|
+
outcome:
|
|
201
|
+
'The worker reports the persistence failure loudly; bounded recovery may repeat work whose completion was not durable.',
|
|
202
|
+
safetyFacts: ['retry_or_explicit_recovery', 'bounded_provider_execution'],
|
|
203
|
+
},
|
|
204
|
+
verification: {
|
|
205
|
+
kind: 'focused_regression',
|
|
206
|
+
target: 'tests/lib/plays/runtime-test-fault-registry.test.ts',
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'invocation_response_delivery_abort',
|
|
211
|
+
description:
|
|
212
|
+
'Abort one receipt-gateway response after invocation delivery.',
|
|
213
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
214
|
+
control: {
|
|
215
|
+
kind: 'runtime_test_fault',
|
|
216
|
+
defaultValue: 1,
|
|
217
|
+
valueMeaning: 'occurrence',
|
|
218
|
+
},
|
|
219
|
+
expected: {
|
|
220
|
+
outcome:
|
|
221
|
+
'The same logical run completes through receipt replay; recovery remains bounded if the provider outcome must be retried.',
|
|
222
|
+
safetyFacts: ['same_logical_run', 'bounded_provider_execution'],
|
|
223
|
+
},
|
|
224
|
+
verification: {
|
|
225
|
+
kind: 'local_black_box',
|
|
226
|
+
target: 'invocation-delivery-replay-e2e',
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
{
|
|
230
|
+
id: 'receipt_gateway_hold_ms',
|
|
231
|
+
description: 'Hold one checked-out receipt-gateway scheduler client.',
|
|
232
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
233
|
+
control: {
|
|
234
|
+
kind: 'runtime_test_fault',
|
|
235
|
+
defaultValue: 500,
|
|
236
|
+
valueMeaning: 'milliseconds',
|
|
237
|
+
},
|
|
238
|
+
expected: {
|
|
239
|
+
outcome:
|
|
240
|
+
'The request is delayed inside the real gateway pool and either completes within its deadline or follows bounded transport recovery.',
|
|
241
|
+
safetyFacts: ['bounded_provider_execution'],
|
|
242
|
+
},
|
|
243
|
+
verification: {
|
|
244
|
+
kind: 'local_black_box',
|
|
245
|
+
target: 'agent-heavy-gateway-load-e2e',
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
id: 'receipt_claim_query_hold_once_ms',
|
|
250
|
+
description: 'Hold one physical receipt-claim query.',
|
|
251
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
252
|
+
control: {
|
|
253
|
+
kind: 'runtime_test_fault',
|
|
254
|
+
defaultValue: 500,
|
|
255
|
+
valueMeaning: 'milliseconds',
|
|
256
|
+
},
|
|
257
|
+
expected: {
|
|
258
|
+
outcome:
|
|
259
|
+
'The checked-out claim either completes or times out through bounded recovery; an ambiguous outcome may be retried within its budget.',
|
|
260
|
+
safetyFacts: ['bounded_provider_execution'],
|
|
261
|
+
},
|
|
262
|
+
verification: {
|
|
263
|
+
kind: 'local_black_box',
|
|
264
|
+
target: 'receipt-claim-deadline-recovery-e2e',
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
id: 'receipt_claim_response_timeout',
|
|
269
|
+
description:
|
|
270
|
+
'Report one fully received receipt-claim response as timed out.',
|
|
271
|
+
topologies: LOCAL_AND_PREVIEW_TOPOLOGIES,
|
|
272
|
+
control: {
|
|
273
|
+
kind: 'runtime_test_fault',
|
|
274
|
+
defaultValue: 1,
|
|
275
|
+
valueMeaning: 'occurrence',
|
|
276
|
+
},
|
|
277
|
+
expected: {
|
|
278
|
+
outcome:
|
|
279
|
+
'The same logical run completes by replaying the committed receipt response or uses bounded recovery if that response is unavailable.',
|
|
280
|
+
safetyFacts: ['same_logical_run', 'bounded_provider_execution'],
|
|
281
|
+
},
|
|
282
|
+
verification: {
|
|
283
|
+
kind: 'local_black_box',
|
|
284
|
+
target: 'receipt-ambiguous-response-recovery-e2e',
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: 'modal_sandbox_create_resource_exhausted',
|
|
289
|
+
description:
|
|
290
|
+
'Make Modal sandbox creation return RESOURCE_EXHAUSTED before user code.',
|
|
291
|
+
topologies: MODAL_PREVIEW_TOPOLOGY,
|
|
292
|
+
control: {
|
|
293
|
+
kind: 'runtime_test_fault',
|
|
294
|
+
defaultValue: 1,
|
|
295
|
+
valueMeaning: 'occurrence',
|
|
296
|
+
},
|
|
297
|
+
expected: {
|
|
298
|
+
outcome:
|
|
299
|
+
'The same logical run enters bounded pre-code defer/recovery and later retries sandbox startup; no user code or provider call precedes the retry.',
|
|
300
|
+
safetyFacts: [
|
|
301
|
+
'same_logical_run',
|
|
302
|
+
'no_user_code_before_recovery',
|
|
303
|
+
'bounded_provider_execution',
|
|
304
|
+
],
|
|
305
|
+
},
|
|
306
|
+
verification: {
|
|
307
|
+
kind: 'preview_black_box',
|
|
308
|
+
target: 'modal-sandbox-recovery-e2e',
|
|
309
|
+
},
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
id: 'runtime_sheet_page_tail_hold_ms',
|
|
313
|
+
description: 'Hold one runtime-sheet tail-page operation.',
|
|
314
|
+
topologies: LOCAL_TOPOLOGY,
|
|
315
|
+
control: {
|
|
316
|
+
kind: 'runtime_test_fault',
|
|
317
|
+
defaultValue: 500,
|
|
318
|
+
valueMeaning: 'milliseconds',
|
|
319
|
+
},
|
|
320
|
+
expected: {
|
|
321
|
+
outcome:
|
|
322
|
+
'Page-tail work stays pending during the bounded hold, then completes without losing or duplicating rows.',
|
|
323
|
+
safetyFacts: ['all_rows_settle_once'],
|
|
324
|
+
},
|
|
325
|
+
verification: {
|
|
326
|
+
kind: 'local_black_box',
|
|
327
|
+
target: 'page-tail-sheet-write-hold-e2e',
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
];
|
|
331
|
+
|
|
332
|
+
export type RuntimeTestFaultDrill = Omit<
|
|
333
|
+
RuntimeIncidentDrill,
|
|
334
|
+
'id' | 'control'
|
|
335
|
+
> &
|
|
336
|
+
Readonly<{
|
|
337
|
+
id: RuntimeTestFaultName;
|
|
338
|
+
control: Readonly<{
|
|
339
|
+
kind: 'runtime_test_fault';
|
|
340
|
+
defaultValue: number;
|
|
341
|
+
valueMeaning: 'occurrence' | 'milliseconds';
|
|
342
|
+
}>;
|
|
343
|
+
}>;
|
|
344
|
+
|
|
345
|
+
function isRuntimeTestFaultDrill(
|
|
346
|
+
drill: RuntimeIncidentDrill,
|
|
347
|
+
): drill is RuntimeTestFaultDrill {
|
|
348
|
+
return (
|
|
349
|
+
drill.control.kind === 'runtime_test_fault' &&
|
|
350
|
+
RUNTIME_TEST_FAULT_IDS.some((faultId) => faultId === drill.id)
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function runtimeTestFaultDrills(): readonly RuntimeTestFaultDrill[] {
|
|
355
|
+
return RUNTIME_INCIDENT_DRILL_CATALOG.filter(isRuntimeTestFaultDrill);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
export function findRuntimeIncidentDrill(
|
|
359
|
+
id: string,
|
|
360
|
+
): RuntimeIncidentDrill | null {
|
|
361
|
+
return (
|
|
362
|
+
RUNTIME_INCIDENT_DRILL_CATALOG.find((drill) => drill.id === id) ?? null
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
export function findRuntimeTestFaultDrill(
|
|
367
|
+
id: string,
|
|
368
|
+
): RuntimeTestFaultDrill | null {
|
|
369
|
+
const drill = findRuntimeIncidentDrill(id);
|
|
370
|
+
return drill && isRuntimeTestFaultDrill(drill) ? drill : null;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export function runtimeIncidentDrillSupportsTopology(
|
|
374
|
+
drill: RuntimeIncidentDrill,
|
|
375
|
+
topology: RuntimeIncidentTopology,
|
|
376
|
+
): boolean {
|
|
377
|
+
return drill.topologies.includes(topology);
|
|
378
|
+
}
|