@skrillex1224/playwright-toolkit 2.1.198 → 2.1.199
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/index.cjs +155 -2
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +155 -2
- package/dist/index.js.map +2 -2
- package/dist/internals/proxy-meter.js +78 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -599,9 +599,31 @@ var logger2 = createInternalLogger("ProxyMeter");
|
|
|
599
599
|
var MAX_TOP_DOMAINS = 20;
|
|
600
600
|
var FLUSH_INTERVAL_MS = 2e3;
|
|
601
601
|
var DEFAULT_DEBUG_MAX_EVENTS = 400;
|
|
602
|
+
var PROXY_METER_READY_TIMEOUT_MS = 5e3;
|
|
603
|
+
var PROXY_METER_STABLE_WINDOW_MS = 2e3;
|
|
604
|
+
var PROXY_METER_POLL_INTERVAL_MS = 100;
|
|
605
|
+
var PROXY_METER_CONNECT_TIMEOUT_MS = 200;
|
|
602
606
|
var runtime = null;
|
|
603
607
|
var cleanupInstalled = false;
|
|
604
608
|
var observedDomainResourceTypes = /* @__PURE__ */ new Map();
|
|
609
|
+
var sleepSignal = new Int32Array(new SharedArrayBuffer(4));
|
|
610
|
+
var portProbeScript = [
|
|
611
|
+
'const net = require("net");',
|
|
612
|
+
"const port = Number(process.argv[1] || 0);",
|
|
613
|
+
"const timeout = Number(process.argv[2] || 200);",
|
|
614
|
+
"if (!Number.isFinite(port) || port <= 0) process.exit(2);",
|
|
615
|
+
'const socket = net.connect({ host: "127.0.0.1", port });',
|
|
616
|
+
"let done = false;",
|
|
617
|
+
"const finish = (code) => {",
|
|
618
|
+
" if (done) return;",
|
|
619
|
+
" done = true;",
|
|
620
|
+
" try { socket.destroy(); } catch {}",
|
|
621
|
+
" process.exit(code);",
|
|
622
|
+
"};",
|
|
623
|
+
'socket.once("connect", () => finish(0));',
|
|
624
|
+
'socket.once("error", () => finish(1));',
|
|
625
|
+
"socket.setTimeout(timeout, () => finish(1));"
|
|
626
|
+
].join("");
|
|
605
627
|
var toSafeInt = (value) => {
|
|
606
628
|
const num = Number(value);
|
|
607
629
|
if (!Number.isFinite(num) || num <= 0) return 0;
|
|
@@ -700,6 +722,17 @@ var ensureLogPath = () => {
|
|
|
700
722
|
const label = runId ? `proxy-meter-${runId}-${suffix}.json` : `proxy-meter-${process.pid}-${suffix}.json`;
|
|
701
723
|
return import_path.default.join(baseDir, label);
|
|
702
724
|
};
|
|
725
|
+
var ensureStatePath = () => {
|
|
726
|
+
const baseDir = resolveLogDir();
|
|
727
|
+
if (!(0, import_fs.existsSync)(baseDir)) {
|
|
728
|
+
try {
|
|
729
|
+
(0, import_fs.mkdirSync)(baseDir, { recursive: true });
|
|
730
|
+
} catch {
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
const suffix = `${Date.now()}-${Math.floor(Math.random() * 1e6)}`;
|
|
734
|
+
return import_path.default.join(baseDir, `proxy-meter-state-${process.pid}-${suffix}.json`);
|
|
735
|
+
};
|
|
703
736
|
var readSnapshot = (logPath) => {
|
|
704
737
|
if (!logPath || !(0, import_fs.existsSync)(logPath)) return null;
|
|
705
738
|
try {
|
|
@@ -710,6 +743,86 @@ var readSnapshot = (logPath) => {
|
|
|
710
743
|
return null;
|
|
711
744
|
}
|
|
712
745
|
};
|
|
746
|
+
var readState = (statePath) => {
|
|
747
|
+
if (!statePath || !(0, import_fs.existsSync)(statePath)) return null;
|
|
748
|
+
try {
|
|
749
|
+
const raw = (0, import_fs.readFileSync)(statePath, "utf8");
|
|
750
|
+
if (!raw) return null;
|
|
751
|
+
return JSON.parse(raw);
|
|
752
|
+
} catch {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
var sleepSync = (durationMs) => {
|
|
757
|
+
const timeout = Math.max(0, Number(durationMs) || 0);
|
|
758
|
+
if (timeout <= 0) return;
|
|
759
|
+
Atomics.wait(sleepSignal, 0, 0, timeout);
|
|
760
|
+
};
|
|
761
|
+
var canConnectToPort = (port, timeoutMs = PROXY_METER_CONNECT_TIMEOUT_MS) => {
|
|
762
|
+
const result = (0, import_child_process.spawnSync)(process.execPath, ["-e", portProbeScript, String(port), String(timeoutMs)], {
|
|
763
|
+
stdio: "ignore",
|
|
764
|
+
timeout: timeoutMs + 100
|
|
765
|
+
});
|
|
766
|
+
return result.status === 0;
|
|
767
|
+
};
|
|
768
|
+
var waitForProxyMeterReady = ({ port, statePath }) => {
|
|
769
|
+
const startedAt = Date.now();
|
|
770
|
+
const listenDeadline = startedAt + PROXY_METER_READY_TIMEOUT_MS;
|
|
771
|
+
let firstConnectAt = 0;
|
|
772
|
+
let stableHealthy = true;
|
|
773
|
+
while (Date.now() < listenDeadline) {
|
|
774
|
+
const lifecycle = readState(statePath);
|
|
775
|
+
if (lifecycle?.status === "exited") {
|
|
776
|
+
return {
|
|
777
|
+
ok: false,
|
|
778
|
+
reason: "child_exit_before_ready",
|
|
779
|
+
childExitCode: lifecycle.exitCode,
|
|
780
|
+
latencyMs: Date.now() - startedAt
|
|
781
|
+
};
|
|
782
|
+
}
|
|
783
|
+
if (canConnectToPort(port)) {
|
|
784
|
+
firstConnectAt = Date.now();
|
|
785
|
+
break;
|
|
786
|
+
}
|
|
787
|
+
sleepSync(PROXY_METER_POLL_INTERVAL_MS);
|
|
788
|
+
}
|
|
789
|
+
if (!firstConnectAt) {
|
|
790
|
+
return {
|
|
791
|
+
ok: false,
|
|
792
|
+
reason: "listen_timeout",
|
|
793
|
+
childExitCode: readState(statePath)?.exitCode ?? null,
|
|
794
|
+
latencyMs: Date.now() - startedAt
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
const stableDeadline = firstConnectAt + PROXY_METER_STABLE_WINDOW_MS;
|
|
798
|
+
while (Date.now() < stableDeadline) {
|
|
799
|
+
const lifecycle = readState(statePath);
|
|
800
|
+
if (lifecycle?.status === "exited") {
|
|
801
|
+
return {
|
|
802
|
+
ok: false,
|
|
803
|
+
reason: "stabilize_timeout",
|
|
804
|
+
childExitCode: lifecycle.exitCode,
|
|
805
|
+
latencyMs: Date.now() - startedAt
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
if (!canConnectToPort(port)) {
|
|
809
|
+
stableHealthy = false;
|
|
810
|
+
}
|
|
811
|
+
sleepSync(PROXY_METER_POLL_INTERVAL_MS);
|
|
812
|
+
}
|
|
813
|
+
if (!stableHealthy || !canConnectToPort(port)) {
|
|
814
|
+
return {
|
|
815
|
+
ok: false,
|
|
816
|
+
reason: "stabilize_timeout",
|
|
817
|
+
childExitCode: readState(statePath)?.exitCode ?? null,
|
|
818
|
+
latencyMs: Date.now() - startedAt
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
return {
|
|
822
|
+
ok: true,
|
|
823
|
+
latencyMs: Date.now() - startedAt
|
|
824
|
+
};
|
|
825
|
+
};
|
|
713
826
|
var normalizeDomainRows = (hosts) => {
|
|
714
827
|
const rows = [];
|
|
715
828
|
let requestCount = 0;
|
|
@@ -858,15 +971,23 @@ var startProxyMeter = (options = {}) => {
|
|
|
858
971
|
const upstreamUrl = String(options.proxyUrl || "").trim();
|
|
859
972
|
if (!upstreamUrl) return null;
|
|
860
973
|
if (runtime && runtime.proc) {
|
|
974
|
+
const previousStatePath = runtime.statePath;
|
|
861
975
|
try {
|
|
862
976
|
runtime.proc.kill("SIGTERM");
|
|
863
977
|
} catch {
|
|
864
978
|
}
|
|
865
979
|
runtime = null;
|
|
980
|
+
if (previousStatePath) {
|
|
981
|
+
try {
|
|
982
|
+
(0, import_fs.rmSync)(previousStatePath, { force: true });
|
|
983
|
+
} catch {
|
|
984
|
+
}
|
|
985
|
+
}
|
|
866
986
|
}
|
|
867
987
|
observedDomainResourceTypes = /* @__PURE__ */ new Map();
|
|
868
988
|
const port = pickFreePort();
|
|
869
989
|
const logPath = ensureLogPath();
|
|
990
|
+
const statePath = ensureStatePath();
|
|
870
991
|
const scriptPath = resolveScriptPath();
|
|
871
992
|
const debugMode = Boolean(options.debugMode);
|
|
872
993
|
const debugMaxEvents = Math.max(10, toSafeInt(options.debugMaxEvents) || DEFAULT_DEBUG_MAX_EVENTS);
|
|
@@ -877,7 +998,8 @@ var startProxyMeter = (options = {}) => {
|
|
|
877
998
|
PROXY_METER_UPSTREAM: upstreamUrl,
|
|
878
999
|
PROXY_METER_FLUSH_MS: String(FLUSH_INTERVAL_MS),
|
|
879
1000
|
PROXY_METER_DEBUG: debugMode ? "1" : "0",
|
|
880
|
-
PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents)
|
|
1001
|
+
PROXY_METER_DEBUG_MAX_EVENTS: String(debugMaxEvents),
|
|
1002
|
+
PROXY_METER_STATE: statePath
|
|
881
1003
|
};
|
|
882
1004
|
const child = (0, import_child_process.spawn)(process.execPath, [scriptPath], {
|
|
883
1005
|
env,
|
|
@@ -892,8 +1014,27 @@ var startProxyMeter = (options = {}) => {
|
|
|
892
1014
|
proc: child,
|
|
893
1015
|
port,
|
|
894
1016
|
logPath,
|
|
1017
|
+
statePath,
|
|
895
1018
|
startedAt: Date.now()
|
|
896
1019
|
};
|
|
1020
|
+
const readiness = waitForProxyMeterReady({ port, statePath });
|
|
1021
|
+
if (!readiness.ok) {
|
|
1022
|
+
logger2.warn(
|
|
1023
|
+
`[proxy-meter] startup failed reason=${readiness.reason} latency_ms=${readiness.latencyMs} exit_code=${readiness.childExitCode ?? "unknown"}`
|
|
1024
|
+
);
|
|
1025
|
+
try {
|
|
1026
|
+
child.kill("SIGTERM");
|
|
1027
|
+
} catch {
|
|
1028
|
+
}
|
|
1029
|
+
runtime = null;
|
|
1030
|
+
try {
|
|
1031
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1032
|
+
} catch {
|
|
1033
|
+
}
|
|
1034
|
+
throw new Error(`proxy-meter startup failed: ${readiness.reason}`);
|
|
1035
|
+
}
|
|
1036
|
+
runtime.startedAt = Date.now() - readiness.latencyMs;
|
|
1037
|
+
logger2.info(`[proxy-meter] ready latency_ms=${readiness.latencyMs} stable_window_ms=${PROXY_METER_STABLE_WINDOW_MS}`);
|
|
897
1038
|
registerCleanup();
|
|
898
1039
|
return { server: `http://127.0.0.1:${port}` };
|
|
899
1040
|
};
|
|
@@ -905,9 +1046,15 @@ var recordProxyMeterResourceType = (requestUrl, resourceType) => {
|
|
|
905
1046
|
};
|
|
906
1047
|
var stopProxyMeter = async () => {
|
|
907
1048
|
if (!runtime) return null;
|
|
908
|
-
const { proc, logPath } = runtime;
|
|
1049
|
+
const { proc, logPath, statePath } = runtime;
|
|
909
1050
|
if (!proc || proc.killed) {
|
|
910
1051
|
runtime = null;
|
|
1052
|
+
if (statePath) {
|
|
1053
|
+
try {
|
|
1054
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1055
|
+
} catch {
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
911
1058
|
return logPath || null;
|
|
912
1059
|
}
|
|
913
1060
|
await new Promise((resolve) => {
|
|
@@ -929,6 +1076,12 @@ var stopProxyMeter = async () => {
|
|
|
929
1076
|
}
|
|
930
1077
|
});
|
|
931
1078
|
runtime = null;
|
|
1079
|
+
if (statePath) {
|
|
1080
|
+
try {
|
|
1081
|
+
(0, import_fs.rmSync)(statePath, { force: true });
|
|
1082
|
+
} catch {
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
932
1085
|
return logPath || null;
|
|
933
1086
|
};
|
|
934
1087
|
var getProxyMeterSnapshot = async (options = {}) => {
|