Files
SerpMax/stress/node-wipe-stress.ts

36 lines
1.6 KiB
TypeScript

/** # 脚本说明
* 节点侧清理:按 pool.json 清单对节点逐个 DELETE /profiles/:fp?force=true
* (admin API 删除不清节点数据;本脚本只处理压测池内的指纹,不动合法 Profile)。
* 用法:bun node-wipe-stress.ts
*/
const fs = require("fs") as typeof import("fs");
const NODE = "http://127.0.0.1:3106";
const DATA = `${new URL(".", import.meta.url).pathname}data`;
const NODE_KEY = /^NODE_KEY=(.*)$/m.exec(fs.readFileSync("/opt/serpmax/node/.env", "utf8"))?.[1]?.trim() ?? "";
const pool = (await Bun.file(`${DATA}/pool.json`).json()) as { fingerprint: string }[];
const fps = [...new Set(pool.map(p => p.fingerprint).filter(Boolean))];
console.log(`[wipe] 池内指纹 ${fps.length} 个`);
let ok = 0, miss = 0, err = 0;
const workers = 12;
let cursor = 0;
async function worker(): Promise<void> {
while (cursor < fps.length) {
const i = cursor++;
const fp = fps[i];
try {
const res = await fetch(`${NODE}/profiles/${fp}?force=true`, {
method: "DELETE",
headers: { "x-node-key": NODE_KEY },
signal: AbortSignal.timeout(30000),
});
if (res.ok) ok++;
else if (res.status === 404) miss++;
else { err++; if (err < 8) console.error(`[wipe] ${fp} -> ${res.status}`); }
} catch { err++; }
}
}
await Promise.all(Array.from({ length: workers }, () => worker()));
console.log(`[wipe] ok=${ok} miss(本就不在)=${miss} err=${err}`);
const left = Bun.spawnSync(["bash", "-c", "ls /opt/serpmax/node/data/profiles/ | wc -l"], { stdout: "pipe" }).stdout.toString().trim();
console.log(`[wipe] 节点目录剩余=${left}`);