deepline 0.3.128 → 0.3.129
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 +34 -9
- package/dist/bundling-sources/sdk/src/http.ts +22 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +22 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +265 -2
- package/dist/bundling-sources/shared_libs/play-runtime/bounded-batch-function.ts +682 -0
- package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +21 -5
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +5390 -1732
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +107 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/commands/roll-execution-relay.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-machines.ts +229 -7
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +25 -4
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-capacity.ts +71 -0
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-gateway-drain.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/runtime-topology.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +694 -28
- package/dist/bundling-sources/shared_libs/play-runtime/egress-bandwidth-probe.ts +167 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +103 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-receipt-output-reference.ts +34 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-gateway-response-size.ts +27 -0
- package/dist/bundling-sources/shared_libs/play-runtime/gateway-postgres-admission.ts +66 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +425 -71
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +210 -32
- package/dist/bundling-sources/shared_libs/play-runtime/governor/in-memory-rate-state-backend.ts +27 -13
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +19 -6
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +61 -2
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/contracts.ts +33 -1
- package/dist/bundling-sources/shared_libs/play-runtime/integration-operation-reader-fence/job.ts +42 -1
- package/dist/bundling-sources/shared_libs/play-runtime/launch-source-policy.ts +11 -11
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +49 -16
- package/dist/bundling-sources/shared_libs/play-runtime/map-memory-limits.ts +1653 -98
- package/dist/bundling-sources/shared_libs/play-runtime/memory-ledger.ts +807 -0
- package/dist/bundling-sources/shared_libs/play-runtime/memory-pressure-signal.ts +138 -0
- package/dist/bundling-sources/shared_libs/play-runtime/output-size-limits.ts +85 -3
- package/dist/bundling-sources/shared_libs/play-runtime/persistence-latch.ts +60 -2
- package/dist/bundling-sources/shared_libs/play-runtime/play-run-recovery-policy.ts +46 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/contracts.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/job.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/ports.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runs/terminal/postgres-adapter.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-runtime-semantics.ts +70 -27
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/adaptive-provider-capacity-controller.ts +192 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/epoch-aimd-rate-controller.ts +194 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/fixture-capacity-simulator.ts +220 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/gradient2-concurrency-controller.ts +214 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-capacity-policy.ts +43 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-concurrency-policy.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-rate-policy.ts +95 -0
- package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-throttle-classifier.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/resource-governor.ts +1535 -11
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +49 -2
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-log-buffer.ts +55 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +221 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +339 -29
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-deadline.ts +28 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-progress-push.ts +192 -165
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-lifecycle.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +90 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-runtime-watchdog.ts +281 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +27 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/local-process.ts +19 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/modal.ts +108 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/runtime-sandbox-reconciliation.ts +40 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/types.ts +11 -5
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-actions.ts +30 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api-compression.ts +276 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +723 -115
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-capacity-policy.ts +98 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-contract.ts +3 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-environment.ts +41 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-flow.ts +448 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-map-row-feed.ts +215 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-store-adapter.ts +161 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-value.ts +184 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-receipt-writer.ts +607 -121
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sandbox-placement-policy.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-row-writer.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/contract.ts +15 -2
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-runs/runner-backend-adapter.ts +71 -14
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-play-deploy-task.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +288 -119
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +8 -6
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-worker-required-env.ts +28 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/canonical-integration-operation-store.ts +179 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-heavy-request-admission.ts +80 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/gateway-progress-registry.ts +31 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-store-contract.ts +104 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-reference.ts +47 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-retirement.ts +193 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/integration-operation-value-storage.ts +420 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +41 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +134 -3
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +1657 -95
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +885 -73
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-completion-coalescer.ts +452 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/receipt-gateway.ts +601 -42
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-terminal-transition.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-receipt-value-storage.ts +371 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/worker-resource-metrics.ts +86 -7
- package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +153 -22
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +188 -38
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +28 -13
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +44 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-result.ts +56 -4
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +16 -10
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +4 -1
- package/dist/cli/index.js +250 -38
- package/dist/cli/index.mjs +250 -38
- package/dist/{compiler-manifest-DfSnbCTW.d.mts → compiler-manifest-BIqRyj5m.d.mts} +1 -1
- package/dist/{compiler-manifest-DfSnbCTW.d.ts → compiler-manifest-BIqRyj5m.d.ts} +1 -1
- package/dist/index.d.mts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +231 -35
- package/dist/index.mjs +231 -35
- package/dist/install-integrity.json +31 -2
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +65 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
export type Gradient2ConcurrencyControllerOptions = Readonly<{
|
|
2
|
+
initialLimit: number;
|
|
3
|
+
minimumLimit: number;
|
|
4
|
+
maximumLimit: number;
|
|
5
|
+
smoothing: number;
|
|
6
|
+
longWindowSmoothing: number;
|
|
7
|
+
rttTolerance: number;
|
|
8
|
+
/** Bounded cold-start probe; one or below preserves ordinary Gradient2. */
|
|
9
|
+
startupProbeMultiplier?: number;
|
|
10
|
+
}>;
|
|
11
|
+
|
|
12
|
+
export type Gradient2Observation = Readonly<{
|
|
13
|
+
kind: 'success' | 'throttled' | 'transport_error';
|
|
14
|
+
latencyMs: number;
|
|
15
|
+
inFlightAtStart?: number;
|
|
16
|
+
}>;
|
|
17
|
+
|
|
18
|
+
export type Gradient2ConcurrencyControllerSnapshot = Readonly<{
|
|
19
|
+
limit: number;
|
|
20
|
+
shortRttMs: number | null;
|
|
21
|
+
longRttMs: number | null;
|
|
22
|
+
minimumRttMs: number | null;
|
|
23
|
+
}>;
|
|
24
|
+
|
|
25
|
+
export type Gradient2ConcurrencyControllerCheckpoint =
|
|
26
|
+
Gradient2ConcurrencyControllerSnapshot &
|
|
27
|
+
Readonly<{
|
|
28
|
+
successfulSamplesInWindow: number;
|
|
29
|
+
windowStartedAtLimit: number;
|
|
30
|
+
/** A real 429 permanently ends exponential startup probing. */
|
|
31
|
+
hasObservedThrottle?: boolean;
|
|
32
|
+
}>;
|
|
33
|
+
|
|
34
|
+
function positive(value: number, label: string): number {
|
|
35
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
36
|
+
throw new Error(`${label} must be finite and greater than zero.`);
|
|
37
|
+
}
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function openFraction(value: number, label: string): number {
|
|
42
|
+
if (!Number.isFinite(value) || value <= 0 || value >= 1) {
|
|
43
|
+
throw new Error(`${label} must be between zero and one.`);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function clamp(value: number, minimum: number, maximum: number): number {
|
|
49
|
+
return Math.min(maximum, Math.max(minimum, value));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Small Gradient2-style concurrency controller.
|
|
54
|
+
*
|
|
55
|
+
* The short RTT follows current pressure. The long RTT follows the provider's
|
|
56
|
+
* uncongested baseline slowly. The controller changes concurrent occupancy,
|
|
57
|
+
* never the requests-per-second target.
|
|
58
|
+
*/
|
|
59
|
+
export class Gradient2ConcurrencyController {
|
|
60
|
+
readonly #minimumLimit: number;
|
|
61
|
+
readonly #maximumLimit: number;
|
|
62
|
+
readonly #smoothing: number;
|
|
63
|
+
readonly #longWindowSmoothing: number;
|
|
64
|
+
readonly #rttTolerance: number;
|
|
65
|
+
readonly #startupProbeMultiplier: number;
|
|
66
|
+
#limit: number;
|
|
67
|
+
#shortRttMs: number | null = null;
|
|
68
|
+
#longRttMs: number | null = null;
|
|
69
|
+
#minimumRttMs: number | null = null;
|
|
70
|
+
#successfulSamplesInWindow = 0;
|
|
71
|
+
#windowStartedAtLimit: number;
|
|
72
|
+
#hasObservedThrottle = false;
|
|
73
|
+
|
|
74
|
+
constructor(
|
|
75
|
+
options: Gradient2ConcurrencyControllerOptions,
|
|
76
|
+
checkpoint?: Gradient2ConcurrencyControllerCheckpoint,
|
|
77
|
+
) {
|
|
78
|
+
this.#minimumLimit = positive(options.minimumLimit, 'Minimum concurrency');
|
|
79
|
+
this.#maximumLimit = positive(options.maximumLimit, 'Maximum concurrency');
|
|
80
|
+
if (this.#maximumLimit < this.#minimumLimit) {
|
|
81
|
+
throw new Error('Maximum concurrency cannot be below the minimum.');
|
|
82
|
+
}
|
|
83
|
+
this.#limit = clamp(
|
|
84
|
+
positive(options.initialLimit, 'Initial concurrency'),
|
|
85
|
+
this.#minimumLimit,
|
|
86
|
+
this.#maximumLimit,
|
|
87
|
+
);
|
|
88
|
+
this.#smoothing = openFraction(options.smoothing, 'Gradient smoothing');
|
|
89
|
+
this.#longWindowSmoothing = openFraction(
|
|
90
|
+
options.longWindowSmoothing,
|
|
91
|
+
'Long-window smoothing',
|
|
92
|
+
);
|
|
93
|
+
this.#rttTolerance = positive(options.rttTolerance, 'RTT tolerance');
|
|
94
|
+
this.#startupProbeMultiplier = Math.max(
|
|
95
|
+
1,
|
|
96
|
+
positive(options.startupProbeMultiplier ?? 1, 'Startup probe multiplier'),
|
|
97
|
+
);
|
|
98
|
+
this.#windowStartedAtLimit = this.#limit;
|
|
99
|
+
if (checkpoint) {
|
|
100
|
+
this.#limit = clamp(
|
|
101
|
+
positive(checkpoint.limit, 'Checkpoint concurrency'),
|
|
102
|
+
this.#minimumLimit,
|
|
103
|
+
this.#maximumLimit,
|
|
104
|
+
);
|
|
105
|
+
this.#shortRttMs = checkpoint.shortRttMs;
|
|
106
|
+
this.#longRttMs = checkpoint.longRttMs;
|
|
107
|
+
this.#minimumRttMs = checkpoint.minimumRttMs;
|
|
108
|
+
this.#successfulSamplesInWindow = Math.max(
|
|
109
|
+
0,
|
|
110
|
+
Math.floor(checkpoint.successfulSamplesInWindow),
|
|
111
|
+
);
|
|
112
|
+
this.#windowStartedAtLimit = clamp(
|
|
113
|
+
positive(
|
|
114
|
+
checkpoint.windowStartedAtLimit,
|
|
115
|
+
'Checkpoint window concurrency',
|
|
116
|
+
),
|
|
117
|
+
this.#minimumLimit,
|
|
118
|
+
this.#maximumLimit,
|
|
119
|
+
);
|
|
120
|
+
this.#hasObservedThrottle = checkpoint.hasObservedThrottle === true;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
observe(observation: Gradient2Observation): void {
|
|
125
|
+
const latencyMs = positive(observation.latencyMs, 'Observed latency');
|
|
126
|
+
if (observation.kind !== 'success') {
|
|
127
|
+
// A transport failure is not provider-capacity evidence. It may still
|
|
128
|
+
// warrant the existing short-term occupancy reduction, but must not
|
|
129
|
+
// permanently prevent an unknown lane from finding its capacity.
|
|
130
|
+
if (observation.kind === 'throttled') {
|
|
131
|
+
this.#hasObservedThrottle = true;
|
|
132
|
+
}
|
|
133
|
+
const signalledCeiling =
|
|
134
|
+
observation.inFlightAtStart === undefined
|
|
135
|
+
? this.#limit
|
|
136
|
+
: Math.max(this.#minimumLimit, observation.inFlightAtStart - 1);
|
|
137
|
+
const decreaseFactor = observation.kind === 'throttled' ? 0.7 : 0.85;
|
|
138
|
+
this.#limit = clamp(
|
|
139
|
+
Math.min(this.#limit * decreaseFactor, signalledCeiling),
|
|
140
|
+
this.#minimumLimit,
|
|
141
|
+
this.#maximumLimit,
|
|
142
|
+
);
|
|
143
|
+
this.#successfulSamplesInWindow = 0;
|
|
144
|
+
this.#windowStartedAtLimit = this.#limit;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
this.#shortRttMs =
|
|
149
|
+
this.#shortRttMs === null
|
|
150
|
+
? latencyMs
|
|
151
|
+
: this.#shortRttMs * (1 - this.#smoothing) +
|
|
152
|
+
latencyMs * this.#smoothing;
|
|
153
|
+
this.#longRttMs =
|
|
154
|
+
this.#longRttMs === null
|
|
155
|
+
? latencyMs
|
|
156
|
+
: this.#longRttMs * (1 - this.#longWindowSmoothing) +
|
|
157
|
+
latencyMs * this.#longWindowSmoothing;
|
|
158
|
+
this.#minimumRttMs =
|
|
159
|
+
this.#minimumRttMs === null
|
|
160
|
+
? latencyMs
|
|
161
|
+
: Math.min(this.#minimumRttMs, latencyMs);
|
|
162
|
+
this.#successfulSamplesInWindow += 1;
|
|
163
|
+
if (
|
|
164
|
+
this.#successfulSamplesInWindow < Math.ceil(this.#windowStartedAtLimit)
|
|
165
|
+
) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const gradient = clamp(
|
|
170
|
+
(this.#rttTolerance * this.#longRttMs) / this.#shortRttMs,
|
|
171
|
+
0.5,
|
|
172
|
+
1,
|
|
173
|
+
);
|
|
174
|
+
const probeHealthy =
|
|
175
|
+
!this.#hasObservedThrottle &&
|
|
176
|
+
this.#startupProbeMultiplier > 1 &&
|
|
177
|
+
gradient >= 1 - this.#smoothing;
|
|
178
|
+
if (probeHealthy) {
|
|
179
|
+
this.#limit = clamp(
|
|
180
|
+
this.#limit * this.#startupProbeMultiplier,
|
|
181
|
+
this.#minimumLimit,
|
|
182
|
+
this.#maximumLimit,
|
|
183
|
+
);
|
|
184
|
+
} else {
|
|
185
|
+
const queueAllowance = Math.sqrt(this.#limit);
|
|
186
|
+
const estimatedLimit = gradient * this.#limit + queueAllowance;
|
|
187
|
+
this.#limit = clamp(
|
|
188
|
+
this.#limit * (1 - this.#smoothing) + estimatedLimit * this.#smoothing,
|
|
189
|
+
this.#minimumLimit,
|
|
190
|
+
this.#maximumLimit,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
this.#successfulSamplesInWindow = 0;
|
|
194
|
+
this.#windowStartedAtLimit = this.#limit;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
snapshot(): Gradient2ConcurrencyControllerSnapshot {
|
|
198
|
+
return Object.freeze({
|
|
199
|
+
limit: this.#limit,
|
|
200
|
+
shortRttMs: this.#shortRttMs,
|
|
201
|
+
longRttMs: this.#longRttMs,
|
|
202
|
+
minimumRttMs: this.#minimumRttMs,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
checkpoint(): Gradient2ConcurrencyControllerCheckpoint {
|
|
207
|
+
return Object.freeze({
|
|
208
|
+
...this.snapshot(),
|
|
209
|
+
successfulSamplesInWindow: this.#successfulSamplesInWindow,
|
|
210
|
+
windowStartedAtLimit: this.#windowStartedAtLimit,
|
|
211
|
+
hasObservedThrottle: this.#hasObservedThrottle,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
}
|
package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-capacity-policy.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical production provider-capacity policy.
|
|
3
|
+
*
|
|
4
|
+
* The topology is deliberately exact: every physical provider start spends
|
|
5
|
+
* shared rate and concurrency authority in one Postgres admission operation.
|
|
6
|
+
* AIMD and Gradient2 are pure transition laws over that shared checkpoint.
|
|
7
|
+
*
|
|
8
|
+
* Keep experimental policy variants in the simulation lab. Production,
|
|
9
|
+
* shadow evaluation, and the winning simulator candidate import this object
|
|
10
|
+
* so tuning cannot drift between the model and the enforced algorithm.
|
|
11
|
+
*/
|
|
12
|
+
export const PROVIDER_CAPACITY_POLICY = Object.freeze({
|
|
13
|
+
id: 'fast_probe_aimd_gradient2',
|
|
14
|
+
admission: 'exact_postgres_per_start',
|
|
15
|
+
rate: Object.freeze({
|
|
16
|
+
epochMs: 1_000,
|
|
17
|
+
recoveryFraction: 0.025,
|
|
18
|
+
// A scope with an explicit exploration ceiling starts with bounded
|
|
19
|
+
// exponential probes. The first authoritative throttle ends probing; all
|
|
20
|
+
// later recovery uses the conservative additive law above.
|
|
21
|
+
startupProbeMultiplier: 2,
|
|
22
|
+
decreaseFactor: 0.4,
|
|
23
|
+
minimumRateFraction: 1 / 16,
|
|
24
|
+
utilizationThreshold: 0.9,
|
|
25
|
+
}),
|
|
26
|
+
concurrency: Object.freeze({
|
|
27
|
+
minimumLimit: 1,
|
|
28
|
+
safetyLimit: 256,
|
|
29
|
+
smoothing: 0.12,
|
|
30
|
+
longWindowSmoothing: 0.03,
|
|
31
|
+
rttTolerance: 1.25,
|
|
32
|
+
startupProbeMultiplier: 2,
|
|
33
|
+
}),
|
|
34
|
+
} as const);
|
|
35
|
+
|
|
36
|
+
export type ProviderCapacityPolicy = typeof PROVIDER_CAPACITY_POLICY;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Cold-start ceiling for an undeclared provider scope. This is a discovery
|
|
40
|
+
* guardrail, not an inferred provider limit; declared rules keep their own
|
|
41
|
+
* hard or advisory ceilings.
|
|
42
|
+
*/
|
|
43
|
+
export const DEFAULT_UNDECLARED_PROVIDER_ADAPTIVE_MAX_RPS = 1_000;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Gradient2ConcurrencyControllerOptions } from './gradient2-concurrency-controller';
|
|
2
|
+
import { PROVIDER_CAPACITY_POLICY } from './provider-capacity-policy';
|
|
3
|
+
|
|
4
|
+
export const PROVIDER_CONCURRENCY_SAFETY_LIMIT =
|
|
5
|
+
PROVIDER_CAPACITY_POLICY.concurrency.safetyLimit;
|
|
6
|
+
|
|
7
|
+
export const PROVIDER_CONCURRENCY_CONTROLLER_TUNING = Object.freeze({
|
|
8
|
+
minimumLimit: PROVIDER_CAPACITY_POLICY.concurrency.minimumLimit,
|
|
9
|
+
smoothing: PROVIDER_CAPACITY_POLICY.concurrency.smoothing,
|
|
10
|
+
longWindowSmoothing: PROVIDER_CAPACITY_POLICY.concurrency.longWindowSmoothing,
|
|
11
|
+
rttTolerance: PROVIDER_CAPACITY_POLICY.concurrency.rttTolerance,
|
|
12
|
+
startupProbeMultiplier:
|
|
13
|
+
PROVIDER_CAPACITY_POLICY.concurrency.startupProbeMultiplier,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The one Gradient2 policy used by Postgres enforcement, shadow evaluation,
|
|
18
|
+
* and simulations. Callers choose only the server-authored initial and maximum
|
|
19
|
+
* limits; algorithm tuning must not drift by deployment surface.
|
|
20
|
+
*/
|
|
21
|
+
export function providerConcurrencyControllerOptions(input: {
|
|
22
|
+
initialLimit: number;
|
|
23
|
+
maximumLimit?: number;
|
|
24
|
+
}): Gradient2ConcurrencyControllerOptions {
|
|
25
|
+
return Object.freeze({
|
|
26
|
+
...PROVIDER_CONCURRENCY_CONTROLLER_TUNING,
|
|
27
|
+
initialLimit: input.initialLimit,
|
|
28
|
+
maximumLimit: input.maximumLimit ?? PROVIDER_CONCURRENCY_SAFETY_LIMIT,
|
|
29
|
+
});
|
|
30
|
+
}
|
package/dist/bundling-sources/shared_libs/play-runtime/provider-capacity/provider-rate-policy.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PROVIDER_CAPACITY_POLICY } from './provider-capacity-policy';
|
|
2
|
+
|
|
3
|
+
export const PROVIDER_RATE_CONTROLLER_TUNING = PROVIDER_CAPACITY_POLICY.rate;
|
|
4
|
+
|
|
5
|
+
export type ProviderRateTargetTransitionInput = Readonly<{
|
|
6
|
+
currentRequestsPerSecond: number;
|
|
7
|
+
minimumRequestsPerSecond: number;
|
|
8
|
+
maximumRequestsPerSecond: number;
|
|
9
|
+
event: 'healthy_epoch' | 'rate_limited';
|
|
10
|
+
additiveIncrease: number;
|
|
11
|
+
decreaseFactor: number;
|
|
12
|
+
}>;
|
|
13
|
+
|
|
14
|
+
function positive(value: number, label: string): number {
|
|
15
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
16
|
+
throw new Error(`${label} must be finite and greater than zero.`);
|
|
17
|
+
}
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Pure transition law for the shared provider start-rate target.
|
|
23
|
+
*
|
|
24
|
+
* Adapters decide when an observation is authoritative. The simulator closes
|
|
25
|
+
* utilization epochs in memory; Postgres applies a healthy-wave transition
|
|
26
|
+
* while holding the credential-scoped rate row and applies a 429 transition
|
|
27
|
+
* only after idempotently recording the physical ticket outcome.
|
|
28
|
+
*/
|
|
29
|
+
export function transitionProviderRateTarget(
|
|
30
|
+
input: ProviderRateTargetTransitionInput,
|
|
31
|
+
): number {
|
|
32
|
+
const minimum = positive(
|
|
33
|
+
input.minimumRequestsPerSecond,
|
|
34
|
+
'Minimum requests per second',
|
|
35
|
+
);
|
|
36
|
+
const maximum = positive(
|
|
37
|
+
input.maximumRequestsPerSecond,
|
|
38
|
+
'Maximum requests per second',
|
|
39
|
+
);
|
|
40
|
+
if (maximum < minimum) {
|
|
41
|
+
throw new Error('Maximum requests per second cannot be below the minimum.');
|
|
42
|
+
}
|
|
43
|
+
const current = Math.min(
|
|
44
|
+
maximum,
|
|
45
|
+
positive(input.currentRequestsPerSecond, 'Current requests per second'),
|
|
46
|
+
);
|
|
47
|
+
const additiveIncrease = positive(
|
|
48
|
+
input.additiveIncrease,
|
|
49
|
+
'Additive increase',
|
|
50
|
+
);
|
|
51
|
+
const decreaseFactor = input.decreaseFactor;
|
|
52
|
+
if (
|
|
53
|
+
!Number.isFinite(decreaseFactor) ||
|
|
54
|
+
decreaseFactor <= 0 ||
|
|
55
|
+
decreaseFactor > 1
|
|
56
|
+
) {
|
|
57
|
+
throw new Error(
|
|
58
|
+
'Decrease factor must be greater than zero and at most one.',
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
if (input.event === 'healthy_epoch') {
|
|
62
|
+
return Math.min(maximum, current + additiveIncrease);
|
|
63
|
+
}
|
|
64
|
+
return Math.max(minimum, current * decreaseFactor);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function providerRateControllerOptions(input: {
|
|
68
|
+
declaredRequestsPerSecond: number;
|
|
69
|
+
initialRequestsPerSecond?: number;
|
|
70
|
+
minimumRequestsPerSecond?: number;
|
|
71
|
+
maximumRequestsPerSecond?: number;
|
|
72
|
+
}) {
|
|
73
|
+
const declared = positive(
|
|
74
|
+
input.declaredRequestsPerSecond,
|
|
75
|
+
'Declared requests per second',
|
|
76
|
+
);
|
|
77
|
+
const maximum = positive(
|
|
78
|
+
input.maximumRequestsPerSecond ?? declared,
|
|
79
|
+
'Maximum requests per second',
|
|
80
|
+
);
|
|
81
|
+
return Object.freeze({
|
|
82
|
+
initialRequestsPerSecond: input.initialRequestsPerSecond ?? declared,
|
|
83
|
+
minimumRequestsPerSecond:
|
|
84
|
+
input.minimumRequestsPerSecond ??
|
|
85
|
+
declared * PROVIDER_RATE_CONTROLLER_TUNING.minimumRateFraction,
|
|
86
|
+
maximumRequestsPerSecond: maximum,
|
|
87
|
+
epochMs: PROVIDER_RATE_CONTROLLER_TUNING.epochMs,
|
|
88
|
+
additiveIncrease:
|
|
89
|
+
declared * PROVIDER_RATE_CONTROLLER_TUNING.recoveryFraction,
|
|
90
|
+
startupProbeMultiplier:
|
|
91
|
+
PROVIDER_RATE_CONTROLLER_TUNING.startupProbeMultiplier,
|
|
92
|
+
decreaseFactor: PROVIDER_RATE_CONTROLLER_TUNING.decreaseFactor,
|
|
93
|
+
utilizationThreshold: PROVIDER_RATE_CONTROLLER_TUNING.utilizationThreshold,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type ProviderConcurrencyGrantToken = Readonly<{
|
|
2
|
+
targetRequestsPerSecond?: number;
|
|
3
|
+
minimumRttMs?: number | null;
|
|
4
|
+
}>;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Classifies one provider 429 from shared rate and RTT evidence.
|
|
8
|
+
*
|
|
9
|
+
* An opaque 429 at more than one in-flight call cannot prove which provider
|
|
10
|
+
* dimension fired. Occupancy materially above the bandwidth-delay product is
|
|
11
|
+
* strong concurrency evidence; lower occupancy remains ambiguous rather than
|
|
12
|
+
* being mislabeled as rate pressure. The caller applies one cautious
|
|
13
|
+
* transition to both controllers for that ambiguous generation.
|
|
14
|
+
*/
|
|
15
|
+
export function classifyProviderThrottle(
|
|
16
|
+
input: Readonly<{
|
|
17
|
+
grant: ProviderConcurrencyGrantToken;
|
|
18
|
+
inFlightAtStart: number;
|
|
19
|
+
}>,
|
|
20
|
+
): 'rate' | 'concurrency' | 'ambiguous' {
|
|
21
|
+
const rate = input.grant.targetRequestsPerSecond;
|
|
22
|
+
const minimumRttMs = input.grant.minimumRttMs;
|
|
23
|
+
if (
|
|
24
|
+
rate === undefined ||
|
|
25
|
+
minimumRttMs === undefined ||
|
|
26
|
+
minimumRttMs === null
|
|
27
|
+
) {
|
|
28
|
+
// A provider rejecting its only active call cannot be proving a positive
|
|
29
|
+
// concurrent-request ceiling. At larger cold occupancies the signal is
|
|
30
|
+
// genuinely ambiguous, so both controllers take one cautious transition.
|
|
31
|
+
return input.inFlightAtStart <= 1 ? 'rate' : 'ambiguous';
|
|
32
|
+
}
|
|
33
|
+
const bandwidthDelayOccupancy = (rate * minimumRttMs) / 1_000;
|
|
34
|
+
const queueAllowance = Math.sqrt(Math.max(1, bandwidthDelayOccupancy));
|
|
35
|
+
return input.inFlightAtStart > bandwidthDelayOccupancy + queueAllowance
|
|
36
|
+
? 'concurrency'
|
|
37
|
+
: input.inFlightAtStart <= 1
|
|
38
|
+
? 'rate'
|
|
39
|
+
: 'ambiguous';
|
|
40
|
+
}
|