@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,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module load-builder
|
|
3
|
+
*
|
|
4
|
+
* Fluent builder for performance transactions (`LoadBuilder`).
|
|
5
|
+
*
|
|
6
|
+
* Entry point: `loadScenario("id")` returns a `LoadBuilder`. Chain
|
|
7
|
+
* `.setup()` → `.step()` → `.teardown()` to define a repeatable transaction;
|
|
8
|
+
* state flows between steps via each step's return value (mirroring
|
|
9
|
+
* `test().builder()`). `.build()` produces a `LoadScenario` consumed by
|
|
10
|
+
* `loadRunner()`.
|
|
11
|
+
*
|
|
12
|
+
* Unlike `TestBuilder`, a `LoadBuilder` does NOT auto-register in the global
|
|
13
|
+
* test registry: a scenario is not independently runnable — only `loadRunner()`
|
|
14
|
+
* exports are scheduled.
|
|
15
|
+
*/
|
|
16
|
+
import { assertSwitchCaseValues } from "../predicates.js";
|
|
17
|
+
import { validatePollBounds } from "../poll-primitives.js";
|
|
18
|
+
// =============================================================================
|
|
19
|
+
// Branch / poll desugar (condition / switchOn / switchCond / poll → one step)
|
|
20
|
+
// =============================================================================
|
|
21
|
+
/** Module-private key holding a load fragment sink's accumulated step list. */
|
|
22
|
+
const FRAGMENT_STEPS = Symbol("glubean.load-fragment-steps");
|
|
23
|
+
function makeStepDef(name, optionsOrFn, maybeFn) {
|
|
24
|
+
const fn = typeof optionsOrFn === "function" ? optionsOrFn : maybeFn;
|
|
25
|
+
const options = typeof optionsOrFn === "function" ? {} : optionsOrFn;
|
|
26
|
+
return {
|
|
27
|
+
meta: { name, ...options },
|
|
28
|
+
fn: fn,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* A branch step carries `branch`; a branch-aware load orchestrator dispatches
|
|
33
|
+
* on it and never calls `fn`. If `fn` IS called the runner is too old to
|
|
34
|
+
* execute load branch steps (SDK/runner version skew) — surface an actionable
|
|
35
|
+
* upgrade message rather than an opaque internal error.
|
|
36
|
+
*/
|
|
37
|
+
function makeBranchStepDef(branch) {
|
|
38
|
+
return {
|
|
39
|
+
meta: { name: branch.message ?? `<${branch.mode}-branch>` },
|
|
40
|
+
fn: (async () => {
|
|
41
|
+
throw new Error(`This load scenario uses condition/switch branching (loadScenario().${branch.mode === "value" ? "switchOn" : "condition/switchCond"}), ` +
|
|
42
|
+
`which requires a @glubean/runner / Glubean CLI new enough to execute load branch steps. ` +
|
|
43
|
+
`Upgrade @glubean/runner and the CLI to match @glubean/sdk.`);
|
|
44
|
+
}),
|
|
45
|
+
branch,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function collectLoadFragment(fn) {
|
|
49
|
+
const result = fn(makeLoadSink([]));
|
|
50
|
+
const steps = result?.[FRAGMENT_STEPS];
|
|
51
|
+
if (!Array.isArray(steps)) {
|
|
52
|
+
throw new Error("a loadScenario() branch body must return the fragment builder " +
|
|
53
|
+
"(e.g. `(b) => b.step(...)` or `(b) => b`); it returned a non-builder value");
|
|
54
|
+
}
|
|
55
|
+
return steps;
|
|
56
|
+
}
|
|
57
|
+
function makeLoadSink(steps) {
|
|
58
|
+
const extend = (s) => makeLoadSink([...steps, s]);
|
|
59
|
+
const sink = {
|
|
60
|
+
step(name, optionsOrFn, maybeFn) {
|
|
61
|
+
return extend(makeStepDef(name, optionsOrFn, maybeFn));
|
|
62
|
+
},
|
|
63
|
+
use(fn) {
|
|
64
|
+
return fn(sink);
|
|
65
|
+
},
|
|
66
|
+
condition(spec, thenB, elseB) {
|
|
67
|
+
return extend(buildLoadConditionStep(spec, thenB, elseB));
|
|
68
|
+
},
|
|
69
|
+
switchOn(lens) {
|
|
70
|
+
return (cases, deflt) => extend(buildLoadSwitchOnStep(lens, cases, deflt));
|
|
71
|
+
},
|
|
72
|
+
switchCond(cases, deflt) {
|
|
73
|
+
return extend(buildLoadSwitchCondStep(cases, deflt));
|
|
74
|
+
},
|
|
75
|
+
poll(name, fn, opts) {
|
|
76
|
+
return extend(buildLoadPollStep(name, fn, opts));
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
Object.defineProperty(sink, FRAGMENT_STEPS, {
|
|
80
|
+
value: Object.freeze(steps),
|
|
81
|
+
enumerable: false,
|
|
82
|
+
});
|
|
83
|
+
return sink;
|
|
84
|
+
}
|
|
85
|
+
/** condition → predicate-mode branch (1 case + default). */
|
|
86
|
+
function buildLoadConditionStep(spec, thenB, elseB) {
|
|
87
|
+
if (!spec || typeof spec.predicate !== "function") {
|
|
88
|
+
throw new Error("loadScenario().condition: spec.predicate must be a function");
|
|
89
|
+
}
|
|
90
|
+
return makeBranchStepDef({
|
|
91
|
+
mode: "predicate",
|
|
92
|
+
...(spec.message ? { message: spec.message } : {}),
|
|
93
|
+
cases: [
|
|
94
|
+
{
|
|
95
|
+
predicate: spec.predicate,
|
|
96
|
+
...(spec.message ? { message: spec.message } : {}),
|
|
97
|
+
steps: collectLoadFragment(thenB),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
default: elseB ? collectLoadFragment(elseB) : [],
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/** switchCond → predicate-mode branch (N cases + default). */
|
|
104
|
+
function buildLoadSwitchCondStep(cases, deflt) {
|
|
105
|
+
return makeBranchStepDef({
|
|
106
|
+
mode: "predicate",
|
|
107
|
+
cases: cases.map((c) => ({ predicate: c.when, steps: collectLoadFragment(c.then) })),
|
|
108
|
+
default: collectLoadFragment(deflt),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/** switchOn → value-mode branch (subject lens evaluated once + scalar match). */
|
|
112
|
+
function buildLoadSwitchOnStep(lens, cases, deflt) {
|
|
113
|
+
assertSwitchCaseValues(cases.map((c) => c.value));
|
|
114
|
+
return makeBranchStepDef({
|
|
115
|
+
mode: "value",
|
|
116
|
+
subject: lens,
|
|
117
|
+
cases: cases.map((c) => ({ value: c.value, steps: collectLoadFragment(c.then) })),
|
|
118
|
+
default: collectLoadFragment(deflt),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
/** A poll step carries `poll`; a poll-aware orchestrator dispatches on it. */
|
|
122
|
+
function makePollStepDef(name, poll) {
|
|
123
|
+
return {
|
|
124
|
+
meta: { name },
|
|
125
|
+
fn: (async () => {
|
|
126
|
+
throw new Error(`This load scenario uses .poll, which requires a @glubean/runner / Glubean CLI ` +
|
|
127
|
+
`new enough to execute load poll steps. Upgrade @glubean/runner and the CLI to match @glubean/sdk.`);
|
|
128
|
+
}),
|
|
129
|
+
poll,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/** loadScenario().poll → a bounded poll-until step (validates bounds at construction). */
|
|
133
|
+
function buildLoadPollStep(name, fn, opts) {
|
|
134
|
+
if (typeof fn !== "function") {
|
|
135
|
+
throw new Error("loadScenario().poll: the attempt `fn` must be a function");
|
|
136
|
+
}
|
|
137
|
+
if (!opts || typeof opts.until !== "function") {
|
|
138
|
+
throw new Error("loadScenario().poll: `opts.until` must be a function");
|
|
139
|
+
}
|
|
140
|
+
validatePollBounds({
|
|
141
|
+
timeout: opts.timeout,
|
|
142
|
+
maxAttempts: opts.maxAttempts,
|
|
143
|
+
perAttemptTimeout: opts.perAttemptTimeout,
|
|
144
|
+
every: opts.every,
|
|
145
|
+
backoff: opts.backoff,
|
|
146
|
+
}, name);
|
|
147
|
+
return makePollStepDef(name, {
|
|
148
|
+
fn,
|
|
149
|
+
until: opts.until,
|
|
150
|
+
...(opts.out ? { out: opts.out } : {}),
|
|
151
|
+
...(opts.every !== undefined ? { every: opts.every } : {}),
|
|
152
|
+
...(opts.backoff !== undefined ? { backoff: opts.backoff } : {}),
|
|
153
|
+
...(opts.timeout !== undefined ? { timeout: opts.timeout } : {}),
|
|
154
|
+
...(opts.perAttemptTimeout !== undefined ? { perAttemptTimeout: opts.perAttemptTimeout } : {}),
|
|
155
|
+
...(opts.maxAttempts !== undefined ? { maxAttempts: opts.maxAttempts } : {}),
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// =============================================================================
|
|
159
|
+
// LoadBuilder
|
|
160
|
+
// =============================================================================
|
|
161
|
+
/**
|
|
162
|
+
* Fluent builder for a performance transaction.
|
|
163
|
+
*
|
|
164
|
+
* @template Input The per-iteration input type (from `loadRunner().input`).
|
|
165
|
+
* @template S The threaded state type.
|
|
166
|
+
*/
|
|
167
|
+
export class LoadBuilder {
|
|
168
|
+
_meta;
|
|
169
|
+
_setup;
|
|
170
|
+
_teardown;
|
|
171
|
+
_steps = [];
|
|
172
|
+
/**
|
|
173
|
+
* Marker so the scanner / loadRunner can detect an un-built LoadBuilder
|
|
174
|
+
* export without importing the SDK.
|
|
175
|
+
*/
|
|
176
|
+
__glubean_type = "load-scenario-builder";
|
|
177
|
+
constructor(id) {
|
|
178
|
+
this._meta = { id };
|
|
179
|
+
}
|
|
180
|
+
/** Set additional scenario metadata. */
|
|
181
|
+
meta(meta) {
|
|
182
|
+
this._meta = { ...this._meta, ...meta };
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
/** Set the setup function that runs before all steps and produces the initial state. */
|
|
186
|
+
setup(fn) {
|
|
187
|
+
this._setup = fn;
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
/** Set the teardown function (always run with the last committed state). */
|
|
191
|
+
teardown(fn) {
|
|
192
|
+
this._teardown = fn;
|
|
193
|
+
return this;
|
|
194
|
+
}
|
|
195
|
+
step(name, optionsOrFn, maybeFn) {
|
|
196
|
+
this._steps.push(makeStepDef(name, optionsOrFn, maybeFn));
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/** Apply a builder transform for reusable step composition (preserves state flow). */
|
|
200
|
+
use(fn) {
|
|
201
|
+
return fn(this);
|
|
202
|
+
}
|
|
203
|
+
/** Apply a builder transform and tag all newly added steps with a group ID. */
|
|
204
|
+
group(id, fn) {
|
|
205
|
+
const before = this._steps.length;
|
|
206
|
+
const result = fn(this);
|
|
207
|
+
for (let i = before; i < this._steps.length; i++) {
|
|
208
|
+
this._steps[i].meta.group = id;
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
condition(spec, thenBranch, elseBranch) {
|
|
213
|
+
this._steps.push(buildLoadConditionStep(spec, thenBranch, elseBranch));
|
|
214
|
+
return this;
|
|
215
|
+
}
|
|
216
|
+
switchOn(lens) {
|
|
217
|
+
return (cases, deflt) => {
|
|
218
|
+
this._steps.push(buildLoadSwitchOnStep(lens, cases, deflt));
|
|
219
|
+
return this;
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
switchCond(cases, deflt) {
|
|
223
|
+
this._steps.push(buildLoadSwitchCondStep(cases, deflt));
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
poll(name, fn, opts) {
|
|
227
|
+
this._steps.push(buildLoadPollStep(name, fn, opts));
|
|
228
|
+
return this;
|
|
229
|
+
}
|
|
230
|
+
/** Build a plain `LoadScenario` definition consumed by `loadRunner()`. */
|
|
231
|
+
build() {
|
|
232
|
+
return {
|
|
233
|
+
__glubean_type: "load-scenario",
|
|
234
|
+
meta: this._meta,
|
|
235
|
+
setup: this._setup,
|
|
236
|
+
steps: this._steps,
|
|
237
|
+
teardown: this._teardown,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Define a performance transaction.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* export const checkoutScenario = loadScenario<CheckoutInput>("checkout")
|
|
247
|
+
* .setup(async (ctx) => ({ user: ctx.input.user, product: ctx.input.product }))
|
|
248
|
+
* .step("login", async (ctx, state) => {
|
|
249
|
+
* const res = await api.post("login", { json: state.user.credentials }).json<{ token: string }>();
|
|
250
|
+
* return { ...state, token: res.token };
|
|
251
|
+
* })
|
|
252
|
+
* .step("checkout", async (ctx, state) => {
|
|
253
|
+
* const res = await api.post("checkout", { headers: { Authorization: `Bearer ${state.token}` } });
|
|
254
|
+
* ctx.expect(res.status).toBe(201).orFail();
|
|
255
|
+
* return state;
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
export function loadScenario(id) {
|
|
260
|
+
return new LoadBuilder(id);
|
|
261
|
+
}
|
|
262
|
+
//# sourceMappingURL=builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/load/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load execution context.
|
|
3
|
+
*
|
|
4
|
+
* `LoadContext` is a narrowed `TestContext`: ordinary test-evidence APIs
|
|
5
|
+
* (full trace / metric / action / event / schema validation / memory usage /
|
|
6
|
+
* retry reflection) are removed, and load-only input / identity / report
|
|
7
|
+
* capabilities are added.
|
|
8
|
+
*
|
|
9
|
+
* It deliberately reuses the same runtime-carrier contract as `test()`, so a
|
|
10
|
+
* user's `configure(...)` clients, global `session`, and `vars` / `secrets`
|
|
11
|
+
* work unchanged inside a load scenario — the load runtime just installs a
|
|
12
|
+
* per-iteration runtime (via `runWithRuntime`) instead of a per-test one.
|
|
13
|
+
*/
|
|
14
|
+
import type { TestContext } from "../types.js";
|
|
15
|
+
/** Identity of a primary producer slot (the concurrency unit). */
|
|
16
|
+
export interface LoadProducerSlot {
|
|
17
|
+
id: string;
|
|
18
|
+
index: number;
|
|
19
|
+
}
|
|
20
|
+
/** Identity of one logical scenario iteration (a transaction instance). */
|
|
21
|
+
export interface LoadIteration {
|
|
22
|
+
id: string;
|
|
23
|
+
index: number;
|
|
24
|
+
}
|
|
25
|
+
/** Receipt returned by `ctx.report.primaryComplete()` for diagnostics. */
|
|
26
|
+
export interface LoadPrimaryCompletionReceipt {
|
|
27
|
+
/** Whether this call recorded the primary measurement boundary. */
|
|
28
|
+
measuredPrimaryComplete: boolean;
|
|
29
|
+
/** Whether a producer slot was actually released for back-fill. */
|
|
30
|
+
releasedProducerSlot: boolean;
|
|
31
|
+
/** Whether this was a duplicate boundary call (ignored for scheduling). */
|
|
32
|
+
duplicate: boolean;
|
|
33
|
+
/** How long the call waited on continuation backpressure, in ms. */
|
|
34
|
+
backpressureMs: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Bounded report signals understood by the load runtime. This is NOT a
|
|
38
|
+
* free-form event API like ordinary `ctx.event`; only these signals exist.
|
|
39
|
+
*/
|
|
40
|
+
export interface LoadReportSignal {
|
|
41
|
+
/** Pure report attribution; does not affect scheduling. */
|
|
42
|
+
checkpoint(id: string, data?: Record<string, unknown>): void;
|
|
43
|
+
/**
|
|
44
|
+
* Declare that the primary load for this iteration has been issued, switching
|
|
45
|
+
* the logical iteration into its continuation phase (splits primary vs
|
|
46
|
+
* end-to-end metrics). Pass `releaseProducerSlot: true` to also let the
|
|
47
|
+
* runner back-fill a new primary iteration on this slot.
|
|
48
|
+
*
|
|
49
|
+
* Always `await` it: when `releaseProducerSlot` is set and the continuation
|
|
50
|
+
* backlog is full, it applies producer backpressure.
|
|
51
|
+
*/
|
|
52
|
+
primaryComplete(id: string, data?: Record<string, unknown> & {
|
|
53
|
+
releaseProducerSlot?: true;
|
|
54
|
+
}): Promise<LoadPrimaryCompletionReceipt>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `TestContext` capabilities removed in load mode. These are ordinary
|
|
58
|
+
* test-evidence APIs that would mislead users into expecting contract-grade
|
|
59
|
+
* schema evidence or a full per-request timeline in a load run.
|
|
60
|
+
*/
|
|
61
|
+
export type LoadOmittedContextKeys = "validate" | "trace" | "metric" | "action" | "event" | "getMemoryUsage" | "retryCount";
|
|
62
|
+
/**
|
|
63
|
+
* Load execution context: a narrowed `TestContext` plus load-only members.
|
|
64
|
+
*
|
|
65
|
+
* Retained from `TestContext`: `vars`, `secrets`, `http`, `session`, `log`,
|
|
66
|
+
* `warn`, `expect`, `assert`, `skip`, `fail`, `pollUntil`, `setTimeout`.
|
|
67
|
+
* Added: `input`, `producerSlot`, `iteration`, `now()`, `report`.
|
|
68
|
+
*/
|
|
69
|
+
export type LoadContext<Input = unknown> = Omit<TestContext, LoadOmittedContextKeys> & {
|
|
70
|
+
/** Per-iteration raw input produced by `loadRunner().input`. */
|
|
71
|
+
input: Input;
|
|
72
|
+
/** Identity of the producer slot running this iteration's primary phase. */
|
|
73
|
+
producerSlot: LoadProducerSlot;
|
|
74
|
+
/** Identity of this logical scenario iteration. */
|
|
75
|
+
iteration: LoadIteration;
|
|
76
|
+
/** Monotonic-ish timestamp source for measuring durations within a scenario. */
|
|
77
|
+
now(): number;
|
|
78
|
+
/** Bounded load report signals (checkpoint / primaryComplete). */
|
|
79
|
+
report: LoadReportSignal;
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/load/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,kEAAkE;AAClE,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,0EAA0E;AAC1E,MAAM,WAAW,4BAA4B;IAC3C,mEAAmE;IACnE,uBAAuB,EAAE,OAAO,CAAC;IACjC,mEAAmE;IACnE,oBAAoB,EAAE,OAAO,CAAC;IAC9B,2EAA2E;IAC3E,SAAS,EAAE,OAAO,CAAC;IACnB,oEAAoE;IACpE,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC7D;;;;;;;;OAQG;IACH,eAAe,CACb,EAAE,EAAE,MAAM,EACV,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,mBAAmB,CAAC,EAAE,IAAI,CAAA;KAAE,GAC9D,OAAO,CAAC,4BAA4B,CAAC,CAAC;CAC1C;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAC9B,UAAU,GACV,OAAO,GACP,QAAQ,GACR,QAAQ,GACR,OAAO,GACP,gBAAgB,GAChB,YAAY,CAAC;AAEjB;;;;;;GAMG;AACH,MAAM,MAAM,WAAW,CAAC,KAAK,GAAG,OAAO,IAAI,IAAI,CAC7C,WAAW,EACX,sBAAsB,CACvB,GAAG;IACF,gEAAgE;IAChE,KAAK,EAAE,KAAK,CAAC;IACb,4EAA4E;IAC5E,YAAY,EAAE,gBAAgB,CAAC;IAC/B,mDAAmD;IACnD,SAAS,EAAE,aAAa,CAAC;IACzB,gFAAgF;IAChF,GAAG,IAAI,MAAM,CAAC;IACd,kEAAkE;IAClE,MAAM,EAAE,gBAAgB,CAAC;CAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/load/context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { LoadDuration } from "./runner.js";
|
|
2
|
+
/**
|
|
3
|
+
* Parse a `LoadDuration` into milliseconds.
|
|
4
|
+
*
|
|
5
|
+
* Accepts a number (already ms) or a string with a unit suffix:
|
|
6
|
+
* `"500ms"`, `"60s"`, `"2m"`, `"1h"` (and decimals like `"1.5s"`).
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseDurationMs(duration: LoadDuration): number;
|
|
9
|
+
//# sourceMappingURL=duration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.d.ts","sourceRoot":"","sources":["../../src/load/duration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAiB9D"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a `LoadDuration` into milliseconds.
|
|
3
|
+
*
|
|
4
|
+
* Accepts a number (already ms) or a string with a unit suffix:
|
|
5
|
+
* `"500ms"`, `"60s"`, `"2m"`, `"1h"` (and decimals like `"1.5s"`).
|
|
6
|
+
*/
|
|
7
|
+
export function parseDurationMs(duration) {
|
|
8
|
+
if (typeof duration === "number") {
|
|
9
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
10
|
+
throw new Error(`invalid duration: ${duration} (must be a finite, non-negative number of ms)`);
|
|
11
|
+
}
|
|
12
|
+
return duration;
|
|
13
|
+
}
|
|
14
|
+
const match = duration.trim().match(/^(\d+(?:\.\d+)?)\s*(ms|s|m|h)$/);
|
|
15
|
+
if (!match) {
|
|
16
|
+
throw new Error(`invalid duration string: "${duration}" (use e.g. "500ms", "60s", "2m", "1h")`);
|
|
17
|
+
}
|
|
18
|
+
const value = Number(match[1]);
|
|
19
|
+
const multiplier = match[2] === "ms" ? 1 : match[2] === "s" ? 1000 : match[2] === "m" ? 60_000 : 3_600_000;
|
|
20
|
+
return value * multiplier;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=duration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duration.js","sourceRoot":"","sources":["../../src/load/duration.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,QAAsB;IACpD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,gDAAgD,CAAC,CAAC;QACjG,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtE,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,6BAA6B,QAAQ,yCAAyC,CAC/E,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,UAAU,GACd,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1F,OAAO,KAAK,GAAG,UAAU,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `LoadEvent` — the load runtime's internal fact stream.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately NOT the ordinary `TestEvent` union: a test event is
|
|
5
|
+
* evidence/timeline-shaped (explain why one test failed), while a load event is
|
|
6
|
+
* observation/reduction-shaped (drive bounded real-time aggregation; success
|
|
7
|
+
* paths leave only aggregates, failures leave bounded traces). They may share
|
|
8
|
+
* the envelope / redaction / attribution helpers, but not the union type.
|
|
9
|
+
*
|
|
10
|
+
* The implementation (LoadReducer, sink, orchestrator) lives in @glubean/runner;
|
|
11
|
+
* this is the type contract those modules and external-engine adapters share.
|
|
12
|
+
*/
|
|
13
|
+
import type { LoadArtifactConfig, LoadCrashSummary, LoadErrorKind } from "./artifact.js";
|
|
14
|
+
/** Resolved (ms-normalized) config emitted on `load:start`. */
|
|
15
|
+
export type LoadResolvedConfig = LoadArtifactConfig;
|
|
16
|
+
/** Common attribution carried by every load event. */
|
|
17
|
+
export interface LoadEventEnvelope {
|
|
18
|
+
ts: number;
|
|
19
|
+
seq: number;
|
|
20
|
+
runId: string;
|
|
21
|
+
runnerId: string;
|
|
22
|
+
scenarioId?: string;
|
|
23
|
+
/** Traffic-mix entry id; distinguishes a scenario reused across mix entries. */
|
|
24
|
+
scenarioRefId?: string;
|
|
25
|
+
producerSlotId?: string;
|
|
26
|
+
iterationId?: string;
|
|
27
|
+
stepId?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether this event belongs to primary load generation or a continuation
|
|
30
|
+
* side effect. Switched by the runtime at the first `primaryComplete`, not a
|
|
31
|
+
* user tag; `releaseProducerSlot` affects scheduling, not phase.
|
|
32
|
+
*/
|
|
33
|
+
phase?: "primary" | "continuation";
|
|
34
|
+
}
|
|
35
|
+
/** Why a load run ended. */
|
|
36
|
+
export type LoadEndReason = "duration" | "iterations" | "abort" | "crash";
|
|
37
|
+
/** routeKey provenance for an observed request. */
|
|
38
|
+
export type LoadRouteKeySource = "explicit" | "catalog" | "contract-metadata" | "normalized-url";
|
|
39
|
+
/**
|
|
40
|
+
* The load runtime fact stream. Success requests/assertions feed the reducer
|
|
41
|
+
* only; failures keep bounded traces. Scheduling semantics live on
|
|
42
|
+
* `producer:released` / `producer:releaseRejected` only.
|
|
43
|
+
*/
|
|
44
|
+
export type LoadEvent = (LoadEventEnvelope & {
|
|
45
|
+
type: "load:start";
|
|
46
|
+
config: LoadResolvedConfig;
|
|
47
|
+
}) | (LoadEventEnvelope & {
|
|
48
|
+
type: "load:end";
|
|
49
|
+
reason: LoadEndReason;
|
|
50
|
+
crash?: LoadCrashSummary;
|
|
51
|
+
}) | (LoadEventEnvelope & {
|
|
52
|
+
type: "producerSlot:start";
|
|
53
|
+
producerSlotIndex: number;
|
|
54
|
+
}) | (LoadEventEnvelope & {
|
|
55
|
+
type: "producerSlot:end";
|
|
56
|
+
producerSlotIndex: number;
|
|
57
|
+
primaryIterations: number;
|
|
58
|
+
}) | (LoadEventEnvelope & {
|
|
59
|
+
type: "iteration:start";
|
|
60
|
+
inputKey?: string;
|
|
61
|
+
feederKeys?: Record<string, string>;
|
|
62
|
+
}) | (LoadEventEnvelope & {
|
|
63
|
+
type: "iteration:end";
|
|
64
|
+
ok: boolean;
|
|
65
|
+
durationMs: number;
|
|
66
|
+
errorKind?: LoadErrorKind;
|
|
67
|
+
}) | (LoadEventEnvelope & {
|
|
68
|
+
type: "step:start";
|
|
69
|
+
stepName: string;
|
|
70
|
+
groupId?: string;
|
|
71
|
+
}) | (LoadEventEnvelope & {
|
|
72
|
+
type: "step:end";
|
|
73
|
+
stepName: string;
|
|
74
|
+
ok: boolean;
|
|
75
|
+
durationMs: number;
|
|
76
|
+
skipped?: boolean;
|
|
77
|
+
assertionFailures?: number;
|
|
78
|
+
errorKind?: LoadErrorKind;
|
|
79
|
+
/** Group label — present on step:end so a SKIPPED leaf (which emits no
|
|
80
|
+
* step:start) still carries group attribution. */
|
|
81
|
+
groupId?: string;
|
|
82
|
+
}) | (LoadEventEnvelope & {
|
|
83
|
+
type: "report:checkpoint";
|
|
84
|
+
checkpointId: string;
|
|
85
|
+
data?: Record<string, unknown>;
|
|
86
|
+
}) | (LoadEventEnvelope & {
|
|
87
|
+
type: "producer:primaryCompleted";
|
|
88
|
+
primaryId: string;
|
|
89
|
+
primaryDurationMs: number;
|
|
90
|
+
releaseRequested: boolean;
|
|
91
|
+
}) | (LoadEventEnvelope & {
|
|
92
|
+
type: "producer:released";
|
|
93
|
+
releaseId: string;
|
|
94
|
+
primaryDurationMs: number;
|
|
95
|
+
continuationBacklog: number;
|
|
96
|
+
continuationBackpressure?: boolean;
|
|
97
|
+
backpressureMs: number;
|
|
98
|
+
}) | (LoadEventEnvelope & {
|
|
99
|
+
type: "producer:releaseRejected";
|
|
100
|
+
releaseId: string;
|
|
101
|
+
reason: "continuationBacklogFull" | "duplicateRelease" | "drainTimeout" | "runDeadlineReached";
|
|
102
|
+
waitMs: number;
|
|
103
|
+
continuationBacklog: number;
|
|
104
|
+
}) | (LoadEventEnvelope & {
|
|
105
|
+
type: "request:observed";
|
|
106
|
+
method: string;
|
|
107
|
+
url: string;
|
|
108
|
+
routeKey: string;
|
|
109
|
+
routeKeySource: LoadRouteKeySource;
|
|
110
|
+
routeKeyHeuristic: boolean;
|
|
111
|
+
status?: number;
|
|
112
|
+
ok: boolean;
|
|
113
|
+
durationMs: number;
|
|
114
|
+
bytesIn?: number;
|
|
115
|
+
bytesOut?: number;
|
|
116
|
+
errorKind?: LoadErrorKind;
|
|
117
|
+
}) | (LoadEventEnvelope & {
|
|
118
|
+
type: "assertion:observed";
|
|
119
|
+
passed: boolean;
|
|
120
|
+
message?: string;
|
|
121
|
+
actual?: unknown;
|
|
122
|
+
expected?: unknown;
|
|
123
|
+
}) | (LoadEventEnvelope & {
|
|
124
|
+
type: "log:sampled";
|
|
125
|
+
level: "debug" | "info" | "warn" | "error";
|
|
126
|
+
message: string;
|
|
127
|
+
});
|
|
128
|
+
/** Narrow a LoadEvent to a specific `type`. */
|
|
129
|
+
export type LoadEventOf<T extends LoadEvent["type"]> = Extract<LoadEvent, {
|
|
130
|
+
type: T;
|
|
131
|
+
}>;
|
|
132
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/load/events.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/load/events.ts"],"names":[],"mappings":""}
|