@glubean/sdk 0.5.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/contract-artifacts.d.ts +39 -21
- package/dist/contract-artifacts.d.ts.map +1 -1
- package/dist/contract-artifacts.js +80 -24
- package/dist/contract-artifacts.js.map +1 -1
- package/dist/contract-core.d.ts +10 -21
- package/dist/contract-core.d.ts.map +1 -1
- package/dist/contract-core.js +26 -812
- package/dist/contract-core.js.map +1 -1
- package/dist/contract-http/adapter.d.ts +13 -0
- package/dist/contract-http/adapter.d.ts.map +1 -1
- package/dist/contract-http/adapter.js +191 -23
- package/dist/contract-http/adapter.js.map +1 -1
- package/dist/contract-http/factory.d.ts +2 -2
- package/dist/contract-http/factory.d.ts.map +1 -1
- package/dist/contract-http/factory.js +5 -0
- package/dist/contract-http/factory.js.map +1 -1
- package/dist/contract-http/inbound-match.d.ts +47 -0
- package/dist/contract-http/inbound-match.d.ts.map +1 -0
- package/dist/contract-http/inbound-match.js +136 -0
- package/dist/contract-http/inbound-match.js.map +1 -0
- package/dist/contract-http/inbound-verify.d.ts +46 -0
- package/dist/contract-http/inbound-verify.d.ts.map +1 -0
- package/dist/contract-http/inbound-verify.js +101 -0
- package/dist/contract-http/inbound-verify.js.map +1 -0
- package/dist/contract-http/inbound.d.ts +45 -0
- package/dist/contract-http/inbound.d.ts.map +1 -0
- package/dist/contract-http/inbound.js +89 -0
- package/dist/contract-http/inbound.js.map +1 -0
- package/dist/contract-http/index.d.ts +5 -0
- package/dist/contract-http/index.d.ts.map +1 -1
- package/dist/contract-http/index.js +3 -0
- package/dist/contract-http/index.js.map +1 -1
- package/dist/contract-http/openapi.d.ts +0 -7
- package/dist/contract-http/openapi.d.ts.map +1 -1
- package/dist/contract-http/openapi.js +20 -14
- package/dist/contract-http/openapi.js.map +1 -1
- package/dist/contract-http/types.d.ts +106 -2
- package/dist/contract-http/types.d.ts.map +1 -1
- package/dist/contract-http/types.js +33 -0
- package/dist/contract-http/types.js.map +1 -1
- package/dist/contract-types.d.ts +148 -446
- package/dist/contract-types.d.ts.map +1 -1
- package/dist/data-path.d.ts.map +1 -1
- package/dist/data-path.js +10 -2
- package/dist/data-path.js.map +1 -1
- package/dist/index.d.ts +10 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/internal.d.ts +7 -0
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +14 -0
- package/dist/internal.js.map +1 -1
- package/dist/load/artifact.d.ts +376 -0
- package/dist/load/artifact.d.ts.map +1 -0
- package/dist/load/artifact.js +14 -0
- package/dist/load/artifact.js.map +1 -0
- package/dist/load/builder.d.ts +80 -0
- package/dist/load/builder.d.ts.map +1 -0
- package/dist/load/builder.js +262 -0
- package/dist/load/builder.js.map +1 -0
- package/dist/load/context.d.ts +81 -0
- package/dist/load/context.d.ts.map +1 -0
- package/dist/load/context.js +2 -0
- package/dist/load/context.js.map +1 -0
- package/dist/load/duration.d.ts +9 -0
- package/dist/load/duration.d.ts.map +1 -0
- package/dist/load/duration.js +22 -0
- package/dist/load/duration.js.map +1 -0
- package/dist/load/events.d.ts +132 -0
- package/dist/load/events.d.ts.map +1 -0
- package/dist/load/events.js +2 -0
- package/dist/load/events.js.map +1 -0
- package/dist/load/feeder.d.ts +118 -0
- package/dist/load/feeder.d.ts.map +1 -0
- package/dist/load/feeder.js +170 -0
- package/dist/load/feeder.js.map +1 -0
- package/dist/load/index.d.ts +32 -0
- package/dist/load/index.d.ts.map +1 -0
- package/dist/load/index.js +7 -0
- package/dist/load/index.js.map +1 -0
- package/dist/load/progress.d.ts +56 -0
- package/dist/load/progress.d.ts.map +1 -0
- package/dist/load/progress.js +2 -0
- package/dist/load/progress.js.map +1 -0
- package/dist/load/projection.d.ts +36 -0
- package/dist/load/projection.d.ts.map +1 -0
- package/dist/load/projection.js +47 -0
- package/dist/load/projection.js.map +1 -0
- package/dist/load/runner.d.ts +201 -0
- package/dist/load/runner.d.ts.map +1 -0
- package/dist/load/runner.js +78 -0
- package/dist/load/runner.js.map +1 -0
- package/dist/load/scenario.d.ts +130 -0
- package/dist/load/scenario.d.ts.map +1 -0
- package/dist/load/scenario.js +9 -0
- package/dist/load/scenario.js.map +1 -0
- package/dist/load/step.d.ts +42 -0
- package/dist/load/step.d.ts.map +1 -0
- package/dist/load/step.js +2 -0
- package/dist/load/step.js.map +1 -0
- package/dist/{contract-flow-poll.d.ts → poll-primitives.d.ts} +8 -81
- package/dist/poll-primitives.d.ts.map +1 -0
- package/dist/{contract-flow-poll.js → poll-primitives.js} +10 -64
- package/dist/poll-primitives.js.map +1 -0
- package/dist/{contract-flow-condition.d.ts → predicates.d.ts} +34 -71
- package/dist/predicates.d.ts.map +1 -0
- package/dist/{contract-flow-condition.js → predicates.js} +86 -80
- package/dist/predicates.js.map +1 -0
- package/dist/test/builder.js +2 -2
- package/dist/test/builder.js.map +1 -1
- package/dist/test/utils.d.ts +7 -0
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/utils.js +22 -17
- package/dist/test/utils.js.map +1 -1
- package/dist/types.d.ts +42 -14
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/workflow/builder.d.ts +386 -0
- package/dist/workflow/builder.d.ts.map +1 -0
- package/dist/workflow/builder.js +1150 -0
- package/dist/workflow/builder.js.map +1 -0
- package/dist/workflow/execute.d.ts +277 -0
- package/dist/workflow/execute.d.ts.map +1 -0
- package/dist/workflow/execute.js +1489 -0
- package/dist/workflow/execute.js.map +1 -0
- package/dist/workflow/index.d.ts +11 -0
- package/dist/workflow/index.d.ts.map +1 -0
- package/dist/workflow/index.js +15 -0
- package/dist/workflow/index.js.map +1 -0
- package/dist/workflow/project.d.ts +18 -0
- package/dist/workflow/project.d.ts.map +1 -0
- package/dist/workflow/project.js +321 -0
- package/dist/workflow/project.js.map +1 -0
- package/dist/workflow/retry.d.ts +13 -0
- package/dist/workflow/retry.d.ts.map +1 -0
- package/dist/workflow/retry.js +15 -0
- package/dist/workflow/retry.js.map +1 -0
- package/dist/workflow/types.d.ts +512 -0
- package/dist/workflow/types.d.ts.map +1 -0
- package/dist/workflow/types.js +2 -0
- package/dist/workflow/types.js.map +1 -0
- package/package.json +9 -2
- package/dist/contract-flow-condition.d.ts.map +0 -1
- package/dist/contract-flow-condition.js.map +0 -1
- package/dist/contract-flow-poll.d.ts.map +0 -1
- package/dist/contract-flow-poll.js.map +0 -1
- package/dist/contract-http/flow-helpers.d.ts +0 -12
- package/dist/contract-http/flow-helpers.d.ts.map +0 -1
- package/dist/contract-http/flow-helpers.js +0 -34
- package/dist/contract-http/flow-helpers.js.map +0 -1
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loadRunner(): the pressure model + report model over a loadScenario.
|
|
3
|
+
*
|
|
4
|
+
* `loadRunner()` is the runnable: it references one `loadScenario()` (or a
|
|
5
|
+
* traffic mix of several) and says how much pressure to apply. Discovery
|
|
6
|
+
* (M2) surfaces only `loadRunner()` exports as runnable; the referenced
|
|
7
|
+
* scenarios are workloads, not independently scheduled.
|
|
8
|
+
*
|
|
9
|
+
* M1 is the static authoring surface: `loadRunner()` returns a `LoadPlan`
|
|
10
|
+
* holding the resolved config. Actual execution lives in @glubean/runner.
|
|
11
|
+
*/
|
|
12
|
+
import type { LoadBuilder } from "./builder.js";
|
|
13
|
+
import type { FeederBinding } from "./feeder.js";
|
|
14
|
+
import type { LoadProjection } from "./projection.js";
|
|
15
|
+
import type { LoadScenario } from "./scenario.js";
|
|
16
|
+
import type { LoadAssertionFailureMode } from "./step.js";
|
|
17
|
+
/** A duration as milliseconds (number) or a human string like `"60s"` / `"2m"`. */
|
|
18
|
+
export type LoadDuration = number | string;
|
|
19
|
+
export interface LoadProducerSlotInfo {
|
|
20
|
+
id: string;
|
|
21
|
+
index: number;
|
|
22
|
+
}
|
|
23
|
+
export interface LoadIterationInfo {
|
|
24
|
+
id: string;
|
|
25
|
+
index: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Arguments passed to a function-form `input`. `TRow` is the `loadRunner.each()`
|
|
29
|
+
* row type that produced this plan (typed and present for each variants);
|
|
30
|
+
* `undefined` for non-each plans.
|
|
31
|
+
*/
|
|
32
|
+
export interface LoadInputArgs<TRow = undefined> {
|
|
33
|
+
row: TRow;
|
|
34
|
+
/** Feeder-allocated rows for this iteration, keyed by feeder name. */
|
|
35
|
+
feed: Record<string, any>;
|
|
36
|
+
producerSlot: LoadProducerSlotInfo;
|
|
37
|
+
iteration: LoadIterationInfo;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Per-iteration scenario input. Object form is a static input (same for every
|
|
41
|
+
* iteration); function form is the canonical form when feeders / producer-slot /
|
|
42
|
+
* iteration / `.each()` row participate. There is no hidden merge.
|
|
43
|
+
*/
|
|
44
|
+
export type LoadInputOption<TInput, TRow = undefined> = TInput | ((args: LoadInputArgs<TRow>) => TInput);
|
|
45
|
+
/** Safety valve for `ctx.report.primaryComplete(... releaseProducerSlot: true)`. */
|
|
46
|
+
export interface LoadContinuationConfig {
|
|
47
|
+
maxOutstanding?: number;
|
|
48
|
+
maxConcurrent?: number;
|
|
49
|
+
minPollInterval?: LoadDuration;
|
|
50
|
+
drainTimeout?: LoadDuration;
|
|
51
|
+
onBacklogFull?: "block-producer" | "fail-iteration";
|
|
52
|
+
}
|
|
53
|
+
/** Optional pacing / think-time (MVP may leave unimplemented → back-to-back). */
|
|
54
|
+
export interface LoadPacingConfig {
|
|
55
|
+
thinkTime?: LoadDuration | {
|
|
56
|
+
min: LoadDuration;
|
|
57
|
+
max: LoadDuration;
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
/** Threshold expressions for one scope (e.g. `errorRate: "<1%"`, `p95: "<800ms"`). */
|
|
61
|
+
export interface LoadThresholdScope {
|
|
62
|
+
errorRate?: string;
|
|
63
|
+
p50?: string;
|
|
64
|
+
p90?: string;
|
|
65
|
+
p95?: string;
|
|
66
|
+
p99?: string;
|
|
67
|
+
throughputPerSec?: string;
|
|
68
|
+
backlog?: string;
|
|
69
|
+
backpressureMs?: string;
|
|
70
|
+
}
|
|
71
|
+
/** Structured thresholds. `endpoints` / `steps` are keyed by routeKey / stepId. */
|
|
72
|
+
export interface LoadThresholds {
|
|
73
|
+
transaction?: LoadThresholdScope;
|
|
74
|
+
primary?: LoadThresholdScope;
|
|
75
|
+
endToEnd?: LoadThresholdScope;
|
|
76
|
+
continuation?: LoadThresholdScope;
|
|
77
|
+
endpoints?: Record<string, LoadThresholdScope>;
|
|
78
|
+
steps?: Record<string, LoadThresholdScope>;
|
|
79
|
+
}
|
|
80
|
+
/** Bounded report sampling caps. */
|
|
81
|
+
export interface LoadReportConfig {
|
|
82
|
+
failureTraces?: number;
|
|
83
|
+
slowTransactionSummaries?: number;
|
|
84
|
+
}
|
|
85
|
+
/** A scenario reference: a built `LoadScenario` or an un-built `LoadBuilder`. */
|
|
86
|
+
export type LoadScenarioRef<Input = unknown> = LoadScenario<Input, any> | LoadBuilder<Input, any>;
|
|
87
|
+
type Feeders = Record<string, FeederBinding>;
|
|
88
|
+
interface LoadRunnerCommon {
|
|
89
|
+
concurrency: number;
|
|
90
|
+
duration?: LoadDuration;
|
|
91
|
+
iterations?: number;
|
|
92
|
+
rampUp?: LoadDuration;
|
|
93
|
+
pacing?: LoadPacingConfig;
|
|
94
|
+
continuation?: LoadContinuationConfig;
|
|
95
|
+
assertions?: {
|
|
96
|
+
onFailure?: LoadAssertionFailureMode;
|
|
97
|
+
};
|
|
98
|
+
thresholds?: LoadThresholds;
|
|
99
|
+
report?: LoadReportConfig;
|
|
100
|
+
/** How a run-level abort (stop / duration deadline / SIGINT) reaches in-flight
|
|
101
|
+
* requests.
|
|
102
|
+
* - `"precise"` (default): cancel in-flight HTTP at once. Uses a leak-free
|
|
103
|
+
* per-iteration abort bridge — no per-request listener accumulation.
|
|
104
|
+
* - `"coarse"`: don't wire the abort signal into each request; stop between steps
|
|
105
|
+
* instead. A few % more throughput for high-RPS runs where requests are short,
|
|
106
|
+
* at the cost of letting an already-sent request finish before the run stops. */
|
|
107
|
+
abort?: "precise" | "coarse";
|
|
108
|
+
}
|
|
109
|
+
/** Single-scenario load runner config. `TRow` is the `.each()` row, if any. */
|
|
110
|
+
export interface LoadRunnerConfig<Input = unknown, TRow = undefined> extends LoadRunnerCommon {
|
|
111
|
+
scenario: LoadScenarioRef<Input>;
|
|
112
|
+
feeders?: Feeders;
|
|
113
|
+
input?: LoadInputOption<Input, TRow>;
|
|
114
|
+
}
|
|
115
|
+
/** One entry in a traffic mix. */
|
|
116
|
+
export interface LoadMixEntry<Input = unknown, TRow = undefined> {
|
|
117
|
+
id: string;
|
|
118
|
+
scenario: LoadScenarioRef<Input>;
|
|
119
|
+
weight: number;
|
|
120
|
+
feeders?: Feeders;
|
|
121
|
+
input?: LoadInputOption<Input, TRow>;
|
|
122
|
+
}
|
|
123
|
+
/** Multi-scenario (traffic mix) config. Each entry may have its own input/feeders. */
|
|
124
|
+
export interface LoadMixConfig<TRow = undefined> extends LoadRunnerCommon {
|
|
125
|
+
scenarios: LoadMixEntry<any, TRow>[];
|
|
126
|
+
/** Shared feeders (no Input coupling). Per-entry feeders override these. */
|
|
127
|
+
feeders?: Feeders;
|
|
128
|
+
}
|
|
129
|
+
export type AnyLoadRunnerConfig = LoadRunnerConfig<any, any> | LoadMixConfig<any>;
|
|
130
|
+
/** A runnable load plan (output of `loadRunner()`). */
|
|
131
|
+
export interface LoadPlan {
|
|
132
|
+
readonly __glubean_type: "load-runner";
|
|
133
|
+
id: string;
|
|
134
|
+
config: AnyLoadRunnerConfig;
|
|
135
|
+
/**
|
|
136
|
+
* For `loadRunner.each()` variants: the table row that produced this plan.
|
|
137
|
+
* The load runtime surfaces it to function-form `input` as `args.row`.
|
|
138
|
+
* Absent for non-each plans.
|
|
139
|
+
*/
|
|
140
|
+
row?: Record<string, unknown>;
|
|
141
|
+
/**
|
|
142
|
+
* Plain-data projection of this plan (runnerId / scenarios / steps /
|
|
143
|
+
* normalized durations / threshold scopes), exposed as a lazily-recomputed
|
|
144
|
+
* getter so it always reflects the current config / scenario builders — no
|
|
145
|
+
* stale snapshot if a scenario gains steps after `loadRunner()`. Discovery
|
|
146
|
+
* (scanner / CLI) reads it by duck-typing the exported value: no SDK import
|
|
147
|
+
* and no global registry needed.
|
|
148
|
+
*/
|
|
149
|
+
readonly projection: LoadProjection;
|
|
150
|
+
}
|
|
151
|
+
interface LoadRunnerFn {
|
|
152
|
+
/** Single-scenario load plan. */
|
|
153
|
+
<Input, TRow = undefined>(id: string, config: LoadRunnerConfig<Input, TRow>): LoadPlan;
|
|
154
|
+
/** Traffic-mix load plan. */
|
|
155
|
+
(id: string, config: LoadMixConfig): LoadPlan;
|
|
156
|
+
/**
|
|
157
|
+
* Scenario-level inventory expansion: one load plan per row (e.g. by plan,
|
|
158
|
+
* region, tenant). Each variant has its own id / thresholds / report, and the
|
|
159
|
+
* factory may return a single scenario or a traffic mix. Function-form `input`
|
|
160
|
+
* receives the producing row as a typed `args.row`.
|
|
161
|
+
*/
|
|
162
|
+
each<TRow extends object>(table: readonly TRow[]): <Input>(idTemplate: string, factory: (row: TRow, index: number) => LoadRunnerConfig<Input, TRow> | LoadMixConfig<TRow>) => LoadPlan[];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Define a pressure plan over one or more load scenarios.
|
|
166
|
+
*
|
|
167
|
+
* @example single scenario
|
|
168
|
+
* ```ts
|
|
169
|
+
* export const checkoutLoad = loadRunner("checkout-300", {
|
|
170
|
+
* scenario: checkoutScenario,
|
|
171
|
+
* concurrency: 300,
|
|
172
|
+
* duration: "60s",
|
|
173
|
+
* input: ({ feed, producerSlot, iteration }) => ({
|
|
174
|
+
* user: feed.user,
|
|
175
|
+
* clientRequestId: `${producerSlot.id}-${iteration.id}`,
|
|
176
|
+
* }),
|
|
177
|
+
* thresholds: { transaction: { errorRate: "<1%", p95: "<2000ms" } },
|
|
178
|
+
* });
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
export declare const loadRunner: LoadRunnerFn;
|
|
182
|
+
/**
|
|
183
|
+
* Type-safe constructor for a traffic-mix entry: it binds `input` to the
|
|
184
|
+
* scenario's `Input`, so a mismatched input shape is rejected at author time.
|
|
185
|
+
*
|
|
186
|
+
* Use it inside `scenarios: [...]`. A bare object literal in the array is only
|
|
187
|
+
* checked against `LoadMixEntry<any>` (TypeScript can't infer a distinct `Input`
|
|
188
|
+
* per array element), so wrap each entry with `loadMixEntry()` for per-entry
|
|
189
|
+
* type checking of heterogeneous typed scenarios.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* ```ts
|
|
193
|
+
* scenarios: [
|
|
194
|
+
* loadMixEntry({ id: "checkout", scenario: checkout, weight: 70, input: () => ({ sku: "s" }) }),
|
|
195
|
+
* loadMixEntry({ id: "refund", scenario: refund, weight: 30, input: () => ({ orderId: "o" }) }),
|
|
196
|
+
* ]
|
|
197
|
+
* ```
|
|
198
|
+
*/
|
|
199
|
+
export declare function loadMixEntry<Input, TRow = undefined>(entry: LoadMixEntry<Input, TRow>): LoadMixEntry<any, TRow>;
|
|
200
|
+
export {};
|
|
201
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../src/load/runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { projectLoadPlan } from "./projection.js";
|
|
2
|
+
/** Interpolate `$index` and `$field` placeholders in an `.each()` id template. */
|
|
3
|
+
function interpolateId(template, row, index) {
|
|
4
|
+
// Token-aware: match a whole `$identifier` placeholder, so a field name that
|
|
5
|
+
// prefixes another (possibly missing) longer placeholder can't corrupt it
|
|
6
|
+
// (e.g. `$plan` must not eat the `$plan` inside a missing `$planId`).
|
|
7
|
+
return template.replace(/\$(\w+)/g, (match, name) => {
|
|
8
|
+
if (name === "index")
|
|
9
|
+
return String(index);
|
|
10
|
+
if (Object.prototype.hasOwnProperty.call(row, name))
|
|
11
|
+
return String(row[name]);
|
|
12
|
+
return match; // unknown placeholder — leave intact rather than silently corrupt
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Build a LoadPlan whose `projection` is a lazily-recomputed getter, so it
|
|
17
|
+
* always reflects the current config / scenario builders (no stale snapshot if
|
|
18
|
+
* a scenario gains steps after `loadRunner()` is called).
|
|
19
|
+
*/
|
|
20
|
+
function makeLoadPlan(id, config, row) {
|
|
21
|
+
const plan = {
|
|
22
|
+
__glubean_type: "load-runner",
|
|
23
|
+
id,
|
|
24
|
+
config,
|
|
25
|
+
...(row !== undefined ? { row } : {}),
|
|
26
|
+
};
|
|
27
|
+
Object.defineProperty(plan, "projection", {
|
|
28
|
+
get: () => projectLoadPlan(plan),
|
|
29
|
+
enumerable: true,
|
|
30
|
+
});
|
|
31
|
+
return plan;
|
|
32
|
+
}
|
|
33
|
+
const loadRunnerImpl = (id, config) => makeLoadPlan(id, config);
|
|
34
|
+
loadRunnerImpl.each = (table) => {
|
|
35
|
+
return (idTemplate, factory) => table.map((row, index) => {
|
|
36
|
+
const rowRecord = row;
|
|
37
|
+
return makeLoadPlan(interpolateId(idTemplate, rowRecord, index), factory(row, index), rowRecord);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Define a pressure plan over one or more load scenarios.
|
|
42
|
+
*
|
|
43
|
+
* @example single scenario
|
|
44
|
+
* ```ts
|
|
45
|
+
* export const checkoutLoad = loadRunner("checkout-300", {
|
|
46
|
+
* scenario: checkoutScenario,
|
|
47
|
+
* concurrency: 300,
|
|
48
|
+
* duration: "60s",
|
|
49
|
+
* input: ({ feed, producerSlot, iteration }) => ({
|
|
50
|
+
* user: feed.user,
|
|
51
|
+
* clientRequestId: `${producerSlot.id}-${iteration.id}`,
|
|
52
|
+
* }),
|
|
53
|
+
* thresholds: { transaction: { errorRate: "<1%", p95: "<2000ms" } },
|
|
54
|
+
* });
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export const loadRunner = loadRunnerImpl;
|
|
58
|
+
/**
|
|
59
|
+
* Type-safe constructor for a traffic-mix entry: it binds `input` to the
|
|
60
|
+
* scenario's `Input`, so a mismatched input shape is rejected at author time.
|
|
61
|
+
*
|
|
62
|
+
* Use it inside `scenarios: [...]`. A bare object literal in the array is only
|
|
63
|
+
* checked against `LoadMixEntry<any>` (TypeScript can't infer a distinct `Input`
|
|
64
|
+
* per array element), so wrap each entry with `loadMixEntry()` for per-entry
|
|
65
|
+
* type checking of heterogeneous typed scenarios.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* scenarios: [
|
|
70
|
+
* loadMixEntry({ id: "checkout", scenario: checkout, weight: 70, input: () => ({ sku: "s" }) }),
|
|
71
|
+
* loadMixEntry({ id: "refund", scenario: refund, weight: 30, input: () => ({ orderId: "o" }) }),
|
|
72
|
+
* ]
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export function loadMixEntry(entry) {
|
|
76
|
+
return entry;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.js","sourceRoot":"","sources":["../../src/load/runner.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAmKlD,kFAAkF;AAClF,SAAS,aAAa,CACpB,QAAgB,EAChB,GAA4B,EAC5B,KAAa;IAEb,6EAA6E;IAC7E,0EAA0E;IAC1E,sEAAsE;IACtE,OAAO,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC1D,IAAI,IAAI,KAAK,OAAO;YAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3C,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC;YAAE,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC9E,OAAO,KAAK,CAAC,CAAC,kEAAkE;IAClF,CAAC,CAAC,CAAC;AACL,CAAC;AAwBD;;;;GAIG;AACH,SAAS,YAAY,CACnB,EAAU,EACV,MAA2B,EAC3B,GAA6B;IAE7B,MAAM,IAAI,GAAG;QACX,cAAc,EAAE,aAAsB;QACtC,EAAE;QACF,MAAM;QACN,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACtC,CAAC;IACF,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE;QACxC,GAAG,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC;QAChC,UAAU,EAAE,IAAI;KACjB,CAAC,CAAC;IACH,OAAO,IAAgB,CAAC;AAC1B,CAAC;AAED,MAAM,cAAc,GAAG,CAAC,EAAU,EAAE,MAA2B,EAAY,EAAE,CAC3E,YAAY,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;AAE3B,cAAc,CAAC,IAAI,GAAG,CAAsB,KAAsB,EAAE,EAAE;IACpE,OAAO,CACL,UAAkB,EAClB,OAGwD,EAC5C,EAAE,CACd,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE;QACvB,MAAM,SAAS,GAAG,GAA8B,CAAC;QACjD,OAAO,YAAY,CACjB,aAAa,CAAC,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,EAC3C,OAAO,CAAC,GAAG,EAAE,KAAK,CAAwB,EAC1C,SAAS,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;AACP,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,cAA8B,CAAC;AAEzD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAgC;IAEhC,OAAO,KAAgC,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* loadScenario definition shape + branch/poll runtime data.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the test() step / branch / poll runtime structures, but bind to
|
|
5
|
+
* `LoadContext` and carry a load-specific per-step assertion policy. The load
|
|
6
|
+
* orchestrator (later milestones) executes these. They are intentionally
|
|
7
|
+
* independent of `Test` / `TestEvent` structures so load's bounded-aggregation
|
|
8
|
+
* model never inherits ordinary test timeline semantics.
|
|
9
|
+
*/
|
|
10
|
+
import type { StepJsonScalar, StepMeta, StepNoExtraKeys } from "../types.js";
|
|
11
|
+
import type { LoadContext } from "./context.js";
|
|
12
|
+
import type { LoadAssertionFailureMode, LoadStepOptions } from "./step.js";
|
|
13
|
+
/** Step metadata for a load scenario step: StepMeta plus a load assertion policy. */
|
|
14
|
+
export interface LoadStepMeta extends StepMeta {
|
|
15
|
+
assertions?: {
|
|
16
|
+
onFailure?: LoadAssertionFailureMode;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A scenario step's runtime structure. A normal step has a callable `fn`; a
|
|
21
|
+
* branch step (condition/switch) additionally carries `branch`, and a poll step
|
|
22
|
+
* carries `poll` — for both, `fn` is a throwing stub and the orchestrator
|
|
23
|
+
* dispatches on the extra field.
|
|
24
|
+
*/
|
|
25
|
+
export interface LoadStepDefinition<Input = unknown, S = unknown> {
|
|
26
|
+
meta: LoadStepMeta;
|
|
27
|
+
fn: (ctx: LoadContext<Input>, state: S) => Promise<S | void>;
|
|
28
|
+
branch?: LoadBranchData<Input, S>;
|
|
29
|
+
poll?: LoadPollData<Input, S>;
|
|
30
|
+
}
|
|
31
|
+
/** Runtime branch data (condition / switchOn / switchCond) bound to LoadContext. */
|
|
32
|
+
export interface LoadBranchData<Input = unknown, S = unknown> {
|
|
33
|
+
mode: "predicate" | "value";
|
|
34
|
+
message?: string;
|
|
35
|
+
/** value-mode only: subject lens evaluated once against committed state. */
|
|
36
|
+
subject?: (ctx: LoadContext<Input>, state: S) => unknown;
|
|
37
|
+
cases: Array<{
|
|
38
|
+
predicate?: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
|
|
39
|
+
value?: StepJsonScalar;
|
|
40
|
+
message?: string;
|
|
41
|
+
steps: LoadStepDefinition<Input, S>[];
|
|
42
|
+
}>;
|
|
43
|
+
default: LoadStepDefinition<Input, S>[];
|
|
44
|
+
}
|
|
45
|
+
/** Runtime poll data (bounded poll-until) bound to LoadContext. */
|
|
46
|
+
export interface LoadPollData<Input = unknown, S = unknown> {
|
|
47
|
+
fn: (ctx: LoadContext<Input>, state: S) => Promise<unknown>;
|
|
48
|
+
until: (ctx: LoadContext<Input>, res: unknown, state: S) => boolean | Promise<boolean>;
|
|
49
|
+
out?: (state: S, res: unknown) => unknown;
|
|
50
|
+
every?: number;
|
|
51
|
+
backoff?: number;
|
|
52
|
+
timeout?: number;
|
|
53
|
+
perAttemptTimeout?: number;
|
|
54
|
+
maxAttempts?: number;
|
|
55
|
+
}
|
|
56
|
+
/** Narrow a LoadStepDefinition to a branch step. */
|
|
57
|
+
export declare function isLoadBranchStep<Input, S>(step: LoadStepDefinition<Input, S>): step is LoadStepDefinition<Input, S> & {
|
|
58
|
+
branch: LoadBranchData<Input, S>;
|
|
59
|
+
};
|
|
60
|
+
/** Narrow a LoadStepDefinition to a poll step. */
|
|
61
|
+
export declare function isLoadPollStep<Input, S>(step: LoadStepDefinition<Input, S>): step is LoadStepDefinition<Input, S> & {
|
|
62
|
+
poll: LoadPollData<Input, S>;
|
|
63
|
+
};
|
|
64
|
+
/** `loadScenario().condition` spec — arbitrary runtime predicate. */
|
|
65
|
+
export interface LoadConditionSpec<Input = unknown, S = unknown> {
|
|
66
|
+
predicate: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
|
|
67
|
+
message?: string;
|
|
68
|
+
}
|
|
69
|
+
/** `loadScenario().poll` options. `Res` is inferred from the attempt `fn`'s return. */
|
|
70
|
+
export interface LoadPollOpts<Input, S, Res, NewS> {
|
|
71
|
+
until: (ctx: LoadContext<Input>, res: Res, state: S) => boolean | Promise<boolean>;
|
|
72
|
+
every?: number;
|
|
73
|
+
backoff?: number;
|
|
74
|
+
timeout?: number;
|
|
75
|
+
perAttemptTimeout?: number;
|
|
76
|
+
maxAttempts?: number;
|
|
77
|
+
out?: (state: S, res: Res) => NewS;
|
|
78
|
+
}
|
|
79
|
+
/** Module-private phantom brand making LoadFragmentBuilder invariant in State. */
|
|
80
|
+
declare const LOAD_FRAGMENT_STATE: unique symbol;
|
|
81
|
+
/**
|
|
82
|
+
* Restricted builder for a `loadScenario()` branch body (condition then/else,
|
|
83
|
+
* switch case/default). Exposes step / use / condition / switchOn / switchCond /
|
|
84
|
+
* poll and accumulates them into the branch node; it deliberately does NOT
|
|
85
|
+
* expose setup / teardown / meta / build. Invariant in `State` via the phantom
|
|
86
|
+
* brand (same convergence guarantee as TestFragmentBuilder).
|
|
87
|
+
*/
|
|
88
|
+
export interface LoadFragmentBuilder<Input = unknown, S = unknown> {
|
|
89
|
+
readonly [LOAD_FRAGMENT_STATE]: (s: S) => S;
|
|
90
|
+
step(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<void>): LoadFragmentBuilder<Input, S>;
|
|
91
|
+
step<NewS>(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<NewS>): LoadFragmentBuilder<Input, NewS>;
|
|
92
|
+
step(name: string, options: LoadStepOptions, fn: (ctx: LoadContext<Input>, state: S) => Promise<void>): LoadFragmentBuilder<Input, S>;
|
|
93
|
+
step<NewS>(name: string, options: LoadStepOptions, fn: (ctx: LoadContext<Input>, state: S) => Promise<NewS>): LoadFragmentBuilder<Input, NewS>;
|
|
94
|
+
use<NewS>(fn: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NewS>): LoadFragmentBuilder<Input, NewS>;
|
|
95
|
+
condition<R extends S = S>(spec: LoadConditionSpec<Input, S>, thenBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, R & StepNoExtraKeys<R, S>>): LoadFragmentBuilder<Input, S>;
|
|
96
|
+
condition<T>(spec: LoadConditionSpec<Input, S>, thenBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>, elseBranch: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>): LoadFragmentBuilder<Input, T>;
|
|
97
|
+
switchOn<V>(lens: (ctx: LoadContext<Input>, state: S) => V): <T>(cases: ReadonlyArray<{
|
|
98
|
+
value: [Exclude<Awaited<V>, undefined>] extends [StepJsonScalar] ? Exclude<Awaited<V>, undefined> : never;
|
|
99
|
+
then: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>;
|
|
100
|
+
}>, deflt: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>) => LoadFragmentBuilder<Input, T>;
|
|
101
|
+
switchCond<T>(cases: ReadonlyArray<{
|
|
102
|
+
when: (ctx: LoadContext<Input>, state: S) => boolean | Promise<boolean>;
|
|
103
|
+
then: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, NoInfer<T>>;
|
|
104
|
+
}>, deflt: (b: LoadFragmentBuilder<Input, S>) => LoadFragmentBuilder<Input, T>): LoadFragmentBuilder<Input, T>;
|
|
105
|
+
poll<Res, NewS = S>(name: string, fn: (ctx: LoadContext<Input>, state: S) => Promise<Res>, opts: LoadPollOpts<Input, S, Res, NewS>): LoadFragmentBuilder<Input, NewS>;
|
|
106
|
+
}
|
|
107
|
+
/** Scenario-level metadata. */
|
|
108
|
+
export interface LoadScenarioMeta {
|
|
109
|
+
id: string;
|
|
110
|
+
description?: string;
|
|
111
|
+
/** Scenario-level default for guard/assertion failures. */
|
|
112
|
+
assertions?: {
|
|
113
|
+
onFailure?: LoadAssertionFailureMode;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* A complete loadScenario definition (output of `LoadBuilder.build()`).
|
|
118
|
+
*
|
|
119
|
+
* This is the performance-transaction workload that a `loadRunner()` executes.
|
|
120
|
+
* It is NOT independently runnable — only `loadRunner()` exports are scheduled.
|
|
121
|
+
*/
|
|
122
|
+
export interface LoadScenario<Input = unknown, S = unknown> {
|
|
123
|
+
readonly __glubean_type: "load-scenario";
|
|
124
|
+
meta: LoadScenarioMeta;
|
|
125
|
+
setup?: (ctx: LoadContext<Input>) => Promise<unknown>;
|
|
126
|
+
steps: LoadStepDefinition<Input, unknown>[];
|
|
127
|
+
teardown?: (ctx: LoadContext<Input>, state: S) => Promise<void>;
|
|
128
|
+
}
|
|
129
|
+
export {};
|
|
130
|
+
//# sourceMappingURL=scenario.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario.d.ts","sourceRoot":"","sources":["../../src/load/scenario.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,wBAAwB,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE3E,qFAAqF;AACrF,MAAM,WAAW,YAAa,SAAQ,QAAQ;IAC5C,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,wBAAwB,CAAC;KACtC,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC9D,IAAI,EAAE,YAAY,CAAC;IACnB,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC7D,MAAM,CAAC,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAClC,IAAI,CAAC,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;CAC/B;AAED,oFAAoF;AACpF,MAAM,WAAW,cAAc,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC1D,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC;IACzD,KAAK,EAAE,KAAK,CAAC;QACX,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9E,KAAK,CAAC,EAAE,cAAc,CAAC;QACvB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;KACvC,CAAC,CAAC;IACH,OAAO,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;CACzC;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACxD,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvF,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oDAAoD;AACpD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,CAAC,EACvC,IAAI,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,GACjC,IAAI,IAAI,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG;IAAE,MAAM,EAAE,cAAc,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;CAAE,CAE7E;AAED,kDAAkD;AAClD,wBAAgB,cAAc,CAAC,KAAK,EAAE,CAAC,EACrC,IAAI,EAAE,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,GACjC,IAAI,IAAI,kBAAkB,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;CAAE,CAEzE;AAED,qEAAqE;AACrE,MAAM,WAAW,iBAAiB,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC7D,SAAS,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uFAAuF;AACvF,MAAM,WAAW,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI;IAC/C,KAAK,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,CAAC;CACpC;AAED,kFAAkF;AAClF,OAAO,CAAC,MAAM,mBAAmB,EAAE,OAAO,MAAM,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,WAAW,mBAAmB,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IAC/D,QAAQ,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC;IAE5C,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,EACP,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,CACF,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACjC,IAAI,CAAC,IAAI,EACP,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,eAAe,EACxB,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GACvD,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpC,GAAG,CAAC,IAAI,EACN,EAAE,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,GACzE,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAEpC,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EACvB,IAAI,EAAE,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,EACjC,UAAU,EAAE,CACV,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAC7B,mBAAmB,CAAC,KAAK,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GACzD,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IACjC,SAAS,CAAC,CAAC,EACT,IAAI,EAAE,iBAAiB,CAAC,KAAK,EAAE,CAAC,CAAC,EACjC,UAAU,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,EAC/E,UAAU,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,GACvF,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEjC,QAAQ,CAAC,CAAC,EACR,IAAI,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,CAAC,GAC7C,CAAC,CAAC,EACH,KAAK,EAAE,aAAa,CAAC;QACnB,KAAK,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,GAC5D,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,GAC9B,KAAK,CAAC;QACV,IAAI,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;KACpF,CAAC,EACF,KAAK,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KACvE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEnC,UAAU,CAAC,CAAC,EACV,KAAK,EAAE,aAAa,CAAC;QACnB,IAAI,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QACxE,IAAI,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;KACpF,CAAC,EACF,KAAK,EAAE,CAAC,CAAC,EAAE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,GACzE,mBAAmB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEjC,IAAI,CAAC,GAAG,EAAE,IAAI,GAAG,CAAC,EAChB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,EACvD,IAAI,EAAE,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,GACtC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;CACrC;AAED,+BAA+B;AAC/B,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,wBAAwB,CAAC;KACtC,CAAC;CACH;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY,CAAC,KAAK,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO;IACxD,QAAQ,CAAC,cAAc,EAAE,eAAe,CAAC;IACzC,IAAI,EAAE,gBAAgB,CAAC;IACvB,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACtD,KAAK,EAAE,kBAAkB,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC;IAC5C,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACjE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Narrow a LoadStepDefinition to a branch step. */
|
|
2
|
+
export function isLoadBranchStep(step) {
|
|
3
|
+
return step.branch !== undefined;
|
|
4
|
+
}
|
|
5
|
+
/** Narrow a LoadStepDefinition to a poll step. */
|
|
6
|
+
export function isLoadPollStep(step) {
|
|
7
|
+
return step.poll !== undefined;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=scenario.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../src/load/scenario.ts"],"names":[],"mappings":"AA4DA,oDAAoD;AACpD,MAAM,UAAU,gBAAgB,CAC9B,IAAkC;IAElC,OAAO,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC;AACnC,CAAC;AAED,kDAAkD;AAClD,MAAM,UAAU,cAAc,CAC5B,IAAkC;IAElC,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load scenario step authoring types.
|
|
3
|
+
*
|
|
4
|
+
* These mirror the `test().builder()` step model (return-state threading:
|
|
5
|
+
* a step returns the next state, or `void`/`undefined` to keep the current
|
|
6
|
+
* state) but bind to `LoadContext` and add a load-specific assertion policy.
|
|
7
|
+
*/
|
|
8
|
+
import type { StepMeta } from "../types.js";
|
|
9
|
+
import type { LoadContext } from "./context.js";
|
|
10
|
+
/**
|
|
11
|
+
* What happens when a guard/assertion fails inside a load step.
|
|
12
|
+
*
|
|
13
|
+
* Resolution order (most specific wins):
|
|
14
|
+
* per-assertion `.orFail()` / thrown error
|
|
15
|
+
* > step-level `assertions.onFailure`
|
|
16
|
+
* > scenario-level `assertions.onFailure`
|
|
17
|
+
* > loadRunner `assertions.onFailure`
|
|
18
|
+
* > default `"continue"`
|
|
19
|
+
*/
|
|
20
|
+
export type LoadAssertionFailureMode =
|
|
21
|
+
/** Default: record + count the failure, keep running the scenario. */
|
|
22
|
+
"continue"
|
|
23
|
+
/** Current step completes; remaining steps are skipped. */
|
|
24
|
+
| "skipRemainingSteps"
|
|
25
|
+
/** Fail-fast the current iteration. */
|
|
26
|
+
| "abortIteration";
|
|
27
|
+
/** Per-step options for `loadScenario` steps (`StepMeta` minus `name`, plus load policy). */
|
|
28
|
+
export type LoadStepOptions = Omit<StepMeta, "name"> & {
|
|
29
|
+
assertions?: {
|
|
30
|
+
onFailure?: LoadAssertionFailureMode;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
/** A scenario `setup` producing the initial state from the context. */
|
|
34
|
+
export type LoadSetupFunction<Input, NewState> = (ctx: LoadContext<Input>) => Promise<NewState>;
|
|
35
|
+
/**
|
|
36
|
+
* A scenario step. Returns the next state, or `void`/`undefined` to keep the
|
|
37
|
+
* current state (matching `test().builder()` semantics).
|
|
38
|
+
*/
|
|
39
|
+
export type LoadStepFunction<Input, State, NewState = State> = (ctx: LoadContext<Input>, state: State) => Promise<NewState | void>;
|
|
40
|
+
/** A scenario `teardown`, always run with the last committed state. */
|
|
41
|
+
export type LoadTeardownFunction<Input, State> = (ctx: LoadContext<Input>, state: State) => Promise<void>;
|
|
42
|
+
//# sourceMappingURL=step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.d.ts","sourceRoot":"","sources":["../../src/load/step.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD;;;;;;;;;GASG;AACH,MAAM,MAAM,wBAAwB;AAClC,sEAAsE;AACpE,UAAU;AACZ,2DAA2D;GACzD,oBAAoB;AACtB,uCAAuC;GACrC,gBAAgB,CAAC;AAErB,6FAA6F;AAC7F,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG;IACrD,UAAU,CAAC,EAAE;QACX,SAAS,CAAC,EAAE,wBAAwB,CAAC;KACtC,CAAC;CACH,CAAC;AAEF,uEAAuE;AACvE,MAAM,MAAM,iBAAiB,CAAC,KAAK,EAAE,QAAQ,IAAI,CAC/C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,KACpB,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvB;;;GAGG;AACH,MAAM,MAAM,gBAAgB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,GAAG,KAAK,IAAI,CAC7D,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EACvB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;AAE9B,uEAAuE;AACvE,MAAM,MAAM,oBAAoB,CAAC,KAAK,EAAE,KAAK,IAAI,CAC/C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,EACvB,KAAK,EAAE,KAAK,KACT,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"step.js","sourceRoot":"","sources":["../../src/load/step.ts"],"names":[],"mappings":""}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @module
|
|
2
|
+
* @module poll-primitives
|
|
3
3
|
*
|
|
4
|
-
* Bounded poll-until
|
|
4
|
+
* Bounded poll-until primitives — shared by the vNext `workflow().poll`
|
|
5
|
+
* executor, `test()` helpers, and (until D2 deletes it) the legacy
|
|
6
|
+
* `contract.flow()` loop. Renamed from `contract-flow-poll.ts` (Nv1-D1,
|
|
7
|
+
* 2026-06-13): the quarantine/budget/bounds machinery was never
|
|
8
|
+
* flow-specific. The legacy flow's poll step shapes that used to live here
|
|
9
|
+
* were deleted with the flow itself (Nv1-D2).
|
|
5
10
|
*
|
|
6
11
|
* A poll repeats ONE contract case until an exit predicate over the RESPONSE
|
|
7
12
|
* holds, BOUNDED by a total wall-clock deadline and/or a finite per-attempt
|
|
@@ -15,50 +20,7 @@
|
|
|
15
20
|
* validation, and the JSON-safe projection. The execution LOOP lives in
|
|
16
21
|
* `contract-core.ts` (it needs the shared committed-state cell).
|
|
17
22
|
*/
|
|
18
|
-
import type { ContractCaseRef, ProtocolContract, FieldMapping } from "./contract-types.js";
|
|
19
23
|
import type { TestContext } from "./types.js";
|
|
20
|
-
import { type BranchPredicate, type ExtractedPredicate } from "./contract-flow-condition.js";
|
|
21
|
-
/**
|
|
22
|
-
* Runtime representation of a `flow().poll()` step. Carries live callbacks +
|
|
23
|
-
* the live contract ref. Never serialized — `extractPollStep` produces the
|
|
24
|
-
* JSON-safe form.
|
|
25
|
-
*
|
|
26
|
-
* The exit predicate (`until`) is over the RESPONSE (not state): L2 declarative
|
|
27
|
-
* (`BranchPredicate`, projectable) or opaque (L1 sync / L0 async, marked). The
|
|
28
|
-
* opaque form additionally receives `state` so a poll can wait for the response
|
|
29
|
-
* to reflect something already in state (e.g. `res.version >= state.lastSeen`).
|
|
30
|
-
*/
|
|
31
|
-
export interface RuntimePollStep {
|
|
32
|
-
kind: "poll";
|
|
33
|
-
name?: string;
|
|
34
|
-
ref: ContractCaseRef<any, any, any, any>;
|
|
35
|
-
caseKey: string;
|
|
36
|
-
/** Live contract instance (mirrors ref.contract). */
|
|
37
|
-
contract: ProtocolContract<any, any, any>;
|
|
38
|
-
bindings?: {
|
|
39
|
-
in?: (state: any) => any;
|
|
40
|
-
out?: (state: any, response: any) => any;
|
|
41
|
-
accept?: readonly unknown[];
|
|
42
|
-
};
|
|
43
|
-
/** Exit predicate — L2 declarative (over the response) or opaque (gets ctx, res, state). */
|
|
44
|
-
until: BranchPredicate<any> | {
|
|
45
|
-
kind: "opaque";
|
|
46
|
-
sync: boolean;
|
|
47
|
-
fn: (ctx: TestContext, res: any, state: any) => boolean | Promise<boolean>;
|
|
48
|
-
};
|
|
49
|
-
/** Author-supplied label (opaque tiers require it; L2 can auto-generate). */
|
|
50
|
-
message?: string;
|
|
51
|
-
/** Interval between attempts (ms). */
|
|
52
|
-
every: number;
|
|
53
|
-
/** Multiplier applied to `every` after each retry (1 = fixed). Capped at BACKOFF_CAP_MS. */
|
|
54
|
-
backoff: number;
|
|
55
|
-
/** Total wall-clock bound (ms). */
|
|
56
|
-
timeoutMs?: number;
|
|
57
|
-
/** Per-attempt budget (ms) — required when `timeoutMs` is absent. */
|
|
58
|
-
perAttemptTimeoutMs?: number;
|
|
59
|
-
/** Max attempts (>= 1). */
|
|
60
|
-
maxAttempts?: number;
|
|
61
|
-
}
|
|
62
24
|
/** Backoff cap — mirrors the test() step retry-backoff ceiling. */
|
|
63
25
|
export declare const BACKOFF_CAP_MS = 30000;
|
|
64
26
|
/** Default interval between attempts when `every` is omitted. */
|
|
@@ -104,13 +66,6 @@ export declare function quarantinedCtx(real: TestContext): QuarantinedContext;
|
|
|
104
66
|
* happens defensively).
|
|
105
67
|
*/
|
|
106
68
|
export declare function raceBudget<T>(promise: Promise<T>, budgetMs: number, onTimeout: () => Error): Promise<T>;
|
|
107
|
-
/**
|
|
108
|
-
* Evaluate a poll exit predicate. L2 declarative reads the RESPONSE (`evalPredicate`
|
|
109
|
-
* with subject = response). Opaque tiers get `(ctx, res, state)`. Non-boolean
|
|
110
|
-
* results fail fast (mirrors condition Phase 6); a thrown error / `ctx.skip()`
|
|
111
|
-
* propagates to the caller.
|
|
112
|
-
*/
|
|
113
|
-
export declare function evalPollExit(until: RuntimePollStep["until"], response: unknown, ctx: TestContext, state: unknown): Promise<boolean>;
|
|
114
69
|
/**
|
|
115
70
|
* Validate poll bounds at construction. Two rules (both required), plus
|
|
116
71
|
* finiteness on every timing value (an `Infinity` bound would un-bound the loop):
|
|
@@ -126,32 +81,4 @@ export declare function validatePollBounds(bounds: {
|
|
|
126
81
|
every?: number;
|
|
127
82
|
backoff?: number;
|
|
128
83
|
}, stepLabel: string): void;
|
|
129
|
-
|
|
130
|
-
kind: "poll";
|
|
131
|
-
name?: string;
|
|
132
|
-
contractId: string;
|
|
133
|
-
caseKey: string;
|
|
134
|
-
protocol: string;
|
|
135
|
-
target: string;
|
|
136
|
-
inputs?: FieldMapping[];
|
|
137
|
-
outputs?: FieldMapping[];
|
|
138
|
-
accept?: ReadonlyArray<string | number>;
|
|
139
|
-
/** Exit predicate — L2 precise (compare/in/...) or `{kind:"opaque",...}`. */
|
|
140
|
-
until: ExtractedPredicate;
|
|
141
|
-
message?: string;
|
|
142
|
-
every: number;
|
|
143
|
-
backoff: number;
|
|
144
|
-
timeoutMs?: number;
|
|
145
|
-
perAttemptTimeoutMs?: number;
|
|
146
|
-
maxAttempts?: number;
|
|
147
|
-
}
|
|
148
|
-
/**
|
|
149
|
-
* Normalize a runtime poll step to JSON-safe form. `dryRun` produces the
|
|
150
|
-
* input/output field mappings (the same Proxy dry-run normalizeFlow uses for a
|
|
151
|
-
* contract-call step), so the poll node carries data-flow edges like a step.
|
|
152
|
-
*/
|
|
153
|
-
export declare function extractPollStep(step: RuntimePollStep, dryRun: (step: RuntimePollStep) => {
|
|
154
|
-
inputs?: FieldMapping[];
|
|
155
|
-
outputs?: FieldMapping[];
|
|
156
|
-
}): ExtractedPollStep;
|
|
157
|
-
//# sourceMappingURL=contract-flow-poll.d.ts.map
|
|
84
|
+
//# sourceMappingURL=poll-primitives.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll-primitives.d.ts","sourceRoot":"","sources":["../src/poll-primitives.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAc,MAAM,YAAY,CAAC;AAG1D,mEAAmE;AACnE,eAAO,MAAM,cAAc,QAAS,CAAC;AACrC,iEAAiE;AACjE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAMrC,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBACd,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAQjE;AAMD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,oGAAoG;IACpG,OAAO,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IACnC,6EAA6E;IAC7E,UAAU,IAAI,OAAO,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,kBAAkB,CA2FpE;AAMD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAC1B,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,KAAK,GACrB,OAAO,CAAC,CAAC,CAAC,CAeZ;AAID;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,MAAM,EAAE;IACN,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,EACD,SAAS,EAAE,MAAM,GAChB,IAAI,CA2BN"}
|