next-leak 0.4.2 → 0.4.3
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/{chunk-YDMJVVWG.js → chunk-EQ2DV2YO.js} +77 -24
- package/dist/cli.js +1 -1
- package/dist/control-client.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/ritual.d.ts +3 -0
- package/package.json +1 -1
|
@@ -3657,10 +3657,10 @@ var require_ansi_styles = __commonJS({
|
|
|
3657
3657
|
};
|
|
3658
3658
|
var ansi2ansi = (n) => n;
|
|
3659
3659
|
var rgb2rgb = (r, g, b) => [r, g, b];
|
|
3660
|
-
var setLazyProperty = (object, property,
|
|
3660
|
+
var setLazyProperty = (object, property, get2) => {
|
|
3661
3661
|
Object.defineProperty(object, property, {
|
|
3662
3662
|
get: () => {
|
|
3663
|
-
const value =
|
|
3663
|
+
const value = get2();
|
|
3664
3664
|
Object.defineProperty(object, property, {
|
|
3665
3665
|
value,
|
|
3666
3666
|
enumerable: true,
|
|
@@ -36043,18 +36043,18 @@ var require_gen_mapping_umd = __commonJS({
|
|
|
36043
36043
|
function cast(set) {
|
|
36044
36044
|
return set;
|
|
36045
36045
|
}
|
|
36046
|
-
function
|
|
36046
|
+
function get2(setarr, key) {
|
|
36047
36047
|
return cast(setarr)._indexes[key];
|
|
36048
36048
|
}
|
|
36049
36049
|
function put(setarr, key) {
|
|
36050
|
-
const index =
|
|
36050
|
+
const index = get2(setarr, key);
|
|
36051
36051
|
if (index !== void 0) return index;
|
|
36052
36052
|
const { array, _indexes: indexes } = cast(setarr);
|
|
36053
36053
|
const length = array.push(key);
|
|
36054
36054
|
return indexes[key] = length - 1;
|
|
36055
36055
|
}
|
|
36056
36056
|
function remove(setarr, key) {
|
|
36057
|
-
const index =
|
|
36057
|
+
const index = get2(setarr, key);
|
|
36058
36058
|
if (index === void 0) return;
|
|
36059
36059
|
const { array, _indexes: indexes } = cast(setarr);
|
|
36060
36060
|
for (let i = index + 1; i < array.length; i++) {
|
|
@@ -60212,7 +60212,7 @@ var require_family = __commonJS({
|
|
|
60212
60212
|
});
|
|
60213
60213
|
exports2._getKey = _getKey;
|
|
60214
60214
|
exports2._getPattern = _getPattern;
|
|
60215
|
-
exports2.get =
|
|
60215
|
+
exports2.get = get2;
|
|
60216
60216
|
exports2.getAllNextSiblings = getAllNextSiblings;
|
|
60217
60217
|
exports2.getAllPrevSiblings = getAllPrevSiblings;
|
|
60218
60218
|
exports2.getAssignmentIdentifiers = getAssignmentIdentifiers;
|
|
@@ -60443,7 +60443,7 @@ var require_family = __commonJS({
|
|
|
60443
60443
|
}
|
|
60444
60444
|
return siblings;
|
|
60445
60445
|
}
|
|
60446
|
-
function
|
|
60446
|
+
function get2(key, context = true) {
|
|
60447
60447
|
if (context === true) context = this.context;
|
|
60448
60448
|
const parts = key.split(".");
|
|
60449
60449
|
if (parts.length === 1) {
|
|
@@ -65957,7 +65957,7 @@ var require_dist5 = __commonJS({
|
|
|
65957
65957
|
var pathVar = getPathVar(env, platform);
|
|
65958
65958
|
var separator = getSeparator(platform);
|
|
65959
65959
|
var originalPath = env[pathVar];
|
|
65960
|
-
return { push, unshift, get, restore };
|
|
65960
|
+
return { push, unshift, get: get2, restore };
|
|
65961
65961
|
function push() {
|
|
65962
65962
|
for (var _len = arguments.length, paths = Array(_len), _key = 0; _key < _len; _key++) {
|
|
65963
65963
|
paths[_key] = arguments[_key];
|
|
@@ -65970,12 +65970,12 @@ var require_dist5 = __commonJS({
|
|
|
65970
65970
|
}
|
|
65971
65971
|
return change(false, paths);
|
|
65972
65972
|
}
|
|
65973
|
-
function
|
|
65973
|
+
function get2() {
|
|
65974
65974
|
return env[pathVar];
|
|
65975
65975
|
}
|
|
65976
65976
|
function restore() {
|
|
65977
65977
|
env[pathVar] = originalPath;
|
|
65978
|
-
return
|
|
65978
|
+
return get2();
|
|
65979
65979
|
}
|
|
65980
65980
|
function change(append, paths) {
|
|
65981
65981
|
if (!append) {
|
|
@@ -65986,7 +65986,7 @@ var require_dist5 = __commonJS({
|
|
|
65986
65986
|
addExistingPath(pathArray, env[pathVar], append);
|
|
65987
65987
|
env[pathVar] = pathArray.join(separator);
|
|
65988
65988
|
});
|
|
65989
|
-
return
|
|
65989
|
+
return get2();
|
|
65990
65990
|
}
|
|
65991
65991
|
}
|
|
65992
65992
|
function getPathArray(pathToAdd) {
|
|
@@ -86350,7 +86350,7 @@ var require_form_data = __commonJS({
|
|
|
86350
86350
|
var CombinedStream = require_combined_stream();
|
|
86351
86351
|
var util = __require("util");
|
|
86352
86352
|
var path7 = __require("path");
|
|
86353
|
-
var
|
|
86353
|
+
var http2 = __require("http");
|
|
86354
86354
|
var https = __require("https");
|
|
86355
86355
|
var parseUrl = __require("url").parse;
|
|
86356
86356
|
var fs = __require("fs");
|
|
@@ -86625,7 +86625,7 @@ var require_form_data = __commonJS({
|
|
|
86625
86625
|
if (options.protocol === "https:") {
|
|
86626
86626
|
request2 = https.request(options);
|
|
86627
86627
|
} else {
|
|
86628
|
-
request2 =
|
|
86628
|
+
request2 = http2.request(options);
|
|
86629
86629
|
}
|
|
86630
86630
|
this.getLength(function(err, length) {
|
|
86631
86631
|
if (err && err !== "Unknown stream") {
|
|
@@ -93239,6 +93239,7 @@ async function runLoadPhase(options) {
|
|
|
93239
93239
|
import { mkdir } from "fs/promises";
|
|
93240
93240
|
|
|
93241
93241
|
// src/control-client.ts
|
|
93242
|
+
import http from "http";
|
|
93242
93243
|
import { z as z5 } from "zod";
|
|
93243
93244
|
var sampleSchema = z5.object({
|
|
93244
93245
|
gcExposed: z5.boolean(),
|
|
@@ -93254,19 +93255,70 @@ var ControlError = class extends Error {
|
|
|
93254
93255
|
this.name = "ControlError";
|
|
93255
93256
|
}
|
|
93256
93257
|
};
|
|
93257
|
-
|
|
93258
|
-
|
|
93259
|
-
|
|
93260
|
-
|
|
93261
|
-
|
|
93262
|
-
|
|
93263
|
-
|
|
93258
|
+
var DEADLINES_MS = {
|
|
93259
|
+
"/mem": 3e4,
|
|
93260
|
+
"/gc": 18e4,
|
|
93261
|
+
"/snapshot": 18e5
|
|
93262
|
+
};
|
|
93263
|
+
var DEFAULT_DEADLINE_MS = 3e4;
|
|
93264
|
+
function deadlineFor(pathname) {
|
|
93265
|
+
const operation = pathname.split("?")[0] ?? pathname;
|
|
93266
|
+
return DEADLINES_MS[operation] ?? DEFAULT_DEADLINE_MS;
|
|
93267
|
+
}
|
|
93268
|
+
function get(port, pathname, deadlineMs) {
|
|
93269
|
+
return new Promise((resolve, reject) => {
|
|
93270
|
+
let settled = false;
|
|
93271
|
+
const settle = (outcome) => {
|
|
93272
|
+
if (settled) {
|
|
93273
|
+
return;
|
|
93274
|
+
}
|
|
93275
|
+
settled = true;
|
|
93276
|
+
clearTimeout(timer);
|
|
93277
|
+
if ("ok" in outcome) {
|
|
93278
|
+
resolve(outcome.ok);
|
|
93279
|
+
} else {
|
|
93280
|
+
reject(outcome.error);
|
|
93281
|
+
}
|
|
93282
|
+
};
|
|
93283
|
+
const request2 = http.get({ host: "127.0.0.1", port, path: pathname }, (response) => {
|
|
93284
|
+
const chunks = [];
|
|
93285
|
+
response.on("data", (chunk) => chunks.push(chunk));
|
|
93286
|
+
response.once(
|
|
93287
|
+
"end",
|
|
93288
|
+
() => settle({
|
|
93289
|
+
ok: { status: response.statusCode ?? 0, body: Buffer.concat(chunks).toString("utf8") }
|
|
93290
|
+
})
|
|
93291
|
+
);
|
|
93292
|
+
});
|
|
93293
|
+
const timer = setTimeout(() => {
|
|
93294
|
+
settle({
|
|
93295
|
+
error: new ControlError(
|
|
93296
|
+
`control channel ${pathname} on port ${port} did not answer within ${Math.round(deadlineMs / 1e3)}s \u2014 the measured process is wedged, or this snapshot is larger than anything this tool has been validated on`
|
|
93297
|
+
)
|
|
93298
|
+
});
|
|
93299
|
+
request2.destroy();
|
|
93300
|
+
}, deadlineMs);
|
|
93301
|
+
timer.unref();
|
|
93302
|
+
request2.once(
|
|
93303
|
+
"error",
|
|
93304
|
+
(cause) => settle({
|
|
93305
|
+
error: new ControlError(
|
|
93306
|
+
`control channel ${pathname} on port ${port} did not answer (${cause.message}) \u2014 the measured process is gone or its event loop is blocked`
|
|
93307
|
+
)
|
|
93308
|
+
})
|
|
93264
93309
|
);
|
|
93265
|
-
}
|
|
93266
|
-
|
|
93310
|
+
});
|
|
93311
|
+
}
|
|
93312
|
+
async function request(port, pathname, deadlineMs = deadlineFor(pathname)) {
|
|
93313
|
+
const response = await get(port, pathname, deadlineMs);
|
|
93314
|
+
if (response.status !== 200) {
|
|
93267
93315
|
throw new ControlError(`control channel ${pathname} responded ${response.status}`);
|
|
93268
93316
|
}
|
|
93269
|
-
|
|
93317
|
+
try {
|
|
93318
|
+
return JSON.parse(response.body);
|
|
93319
|
+
} catch {
|
|
93320
|
+
throw new ControlError(`control channel ${pathname} answered with malformed JSON`);
|
|
93321
|
+
}
|
|
93270
93322
|
}
|
|
93271
93323
|
async function requestGc(port) {
|
|
93272
93324
|
const sample = sampleSchema.parse(await request(port, "/gc"));
|
|
@@ -93444,6 +93496,7 @@ async function waitUntilSettled(controlPort, maxIdleMs, deps) {
|
|
|
93444
93496
|
var defaultDeps = {
|
|
93445
93497
|
launch: launchInstrumented,
|
|
93446
93498
|
load: runLoadPhase,
|
|
93499
|
+
abandon: runAbandonPhase,
|
|
93447
93500
|
sleep: (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
|
|
93448
93501
|
readMemory: requestMemory
|
|
93449
93502
|
};
|
|
@@ -93502,7 +93555,7 @@ async function runRitual(options, deps = defaultDeps) {
|
|
|
93502
93555
|
});
|
|
93503
93556
|
return;
|
|
93504
93557
|
}
|
|
93505
|
-
const outcome = await
|
|
93558
|
+
const outcome = await deps.abandon({
|
|
93506
93559
|
url: `http://127.0.0.1:${app.appPort}${options.route}`,
|
|
93507
93560
|
amount,
|
|
93508
93561
|
connections,
|
package/dist/cli.js
CHANGED
package/dist/control-client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HeapSample } from "./control-server.js";
|
|
2
|
+
declare function request(port: number, pathname: string, deadlineMs?: number): Promise<unknown>;
|
|
2
3
|
/** Forces GC in the measured process and returns a settled memory sample. */
|
|
3
4
|
export declare function requestGc(port: number): Promise<HeapSample>;
|
|
4
5
|
/**
|
|
@@ -11,3 +12,6 @@ export declare function requestSnapshot(port: number, name: string): Promise<{
|
|
|
11
12
|
file: string;
|
|
12
13
|
sample: HeapSample;
|
|
13
14
|
}>;
|
|
15
|
+
/** Test seam: the production deadlines would make a hung-server test take minutes. */
|
|
16
|
+
export declare const requestWithDeadline: typeof request;
|
|
17
|
+
export {};
|
package/dist/index.js
CHANGED
package/dist/ritual.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { HeapSample } from "./control-server.js";
|
|
2
2
|
import { launchInstrumented } from "./launcher.js";
|
|
3
|
+
import { runAbandonPhase } from "./abandon-load.js";
|
|
3
4
|
import { runLoadPhase } from "./load.js";
|
|
4
5
|
import { type TrendResult } from "./trend.js";
|
|
5
6
|
export type RitualOptions = {
|
|
@@ -103,6 +104,8 @@ export type RitualResult = {
|
|
|
103
104
|
export type RitualDeps = {
|
|
104
105
|
launch: typeof launchInstrumented;
|
|
105
106
|
load: typeof runLoadPhase;
|
|
107
|
+
/** Early-disconnect load; a seam like `load`, for the same reasons. */
|
|
108
|
+
abandon: typeof runAbandonPhase;
|
|
106
109
|
sleep: (ms: number) => Promise<void>;
|
|
107
110
|
/** GC-free read, polled while the app is under load. */
|
|
108
111
|
readMemory: (port: number) => Promise<HeapSample>;
|