jsir 3.0.9 → 3.1.2

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/deps/room.js CHANGED
@@ -17,6 +17,8 @@ const http = require('http');
17
17
  const tailscalePath = os.platform() === 'darwin' ?
18
18
  '/Applications/Tailscale.app/Contents/MacOS/Tailscale':'tailscale';
19
19
  const packageJson = require("../package.json");
20
+ const { performance } = require('perf_hooks');
21
+ let elu0 = performance.eventLoopUtilization()
20
22
 
21
23
  async function localConfigs(uniqueNameList) {
22
24
  if (uniqueNameList && uniqueNameList.length > 0 ) {
@@ -373,7 +375,7 @@ async function syncConfigs() {
373
375
  let configs;
374
376
  try {
375
377
  configs = await reqFn(setting.configMainFnKey);
376
- console.$msg(`syncConfigs load ${Object.keys(configs)} files`);
378
+ console.$msg(`syncConfigs load ${Object.keys(configs).length} files`);
377
379
  } catch (e) {
378
380
  console.$warn("syncConfigs load failed", e)
379
381
  return;
@@ -417,17 +419,14 @@ async function cleanRoom(room) {
417
419
  }
418
420
 
419
421
  /*
420
- 最小为0
421
- 100 为1 毫秒
422
+ < 0.3 很空
423
+ 0.3 ~ 0.6 正常
424
+ 0.6 ~ 0.8 明显忙
422
425
  */
423
426
  async function getEventLoopDelay() {
424
- const start = process.hrtime.bigint();
425
- const delay = 1; // 用于测量的短暂延迟(单位:毫秒)
426
- const timeoutPromise = new Promise(resolve => setTimeout(resolve, delay));
427
- return await timeoutPromise.then(() => {
428
- const end = process.hrtime.bigint();
429
- return Number(Math.max(Number(end - start) / 1e4 - (delay * 1e2), 0).toFixed(0)); // 避免负值
430
- });
427
+ const cur = performance.eventLoopUtilization(elu0); // 计算这段时间的差分
428
+ elu0 = performance.eventLoopUtilization(); // 更新基准点(关键!)
429
+ return Number(cur.utilization.toFixed(1));
431
430
  }
432
431
 
433
432
  async function initRoomJsir(room) {
@@ -457,7 +456,6 @@ async function initRoomJsir(room) {
457
456
  services[key] = [...new Set(services[key])]
458
457
  }
459
458
  // 初始化jsir
460
- let lastJsir = room.jsirs[process.pid]
461
459
  setting.selfJsir = {
462
460
  pid: process.pid,
463
461
  space: setting.defaultSpace,
@@ -465,7 +463,7 @@ async function initRoomJsir(room) {
465
463
  obj[key] = getValTips()[index];
466
464
  return obj;
467
465
  }, {}),
468
- busy: await getEventLoopDelay() || (lastJsir ? lastJsir.busy:0),
466
+ busy: await getEventLoopDelay(),
469
467
  back: isRunningInBackground(),
470
468
  lastUpdateTime: setting.roomTime,
471
469
  port: setting.server ? setting.server.address()?.port:null,
@@ -589,21 +587,27 @@ async function reqNode(node, method, url, port, body) {
589
587
  }
590
588
 
591
589
  function busyPick(busyItems) {
592
- if (busyItems.length === 1) {
593
- return busyItems[0]
590
+ if (busyItems.length === 1) return busyItems[0];
591
+
592
+ const weights = busyItems.map(item => {
593
+ // ELU 本来就是 0~1,这里只是兜底
594
+ const busy = Math.min(Math.max(item.busy ?? 1, 0), 1);
595
+ return 1 - busy; // 越忙权重越小
596
+ });
597
+
598
+ const total = weights.reduce((a, b) => a + b, 0);
599
+ if (total <= 0) {
600
+ // 所有节点都接近 1(极忙)时,随机选一个
601
+ return busyItems[Math.floor(Math.random() * busyItems.length)];
594
602
  }
595
- // 反转权重:计算 1 / busy 值作为权重
596
- const weights = busyItems.map(item => 1 / (item.busy || 1));
597
- const totalWeight = weights.reduce((sum, weight) => sum + weight, 0);
598
- const random = Math.random() * totalWeight;
599
603
 
600
- let cumulativeWeight = 0;
604
+ let r = Math.random() * total;
601
605
  for (let i = 0; i < busyItems.length; i++) {
602
- cumulativeWeight += weights[i];
603
- if (random < cumulativeWeight) {
604
- return busyItems[i]; // 选中反转权重命中的对象
605
- }
606
+ r -= weights[i];
607
+ if (r <= 0) return busyItems[i];
606
608
  }
609
+
610
+ return busyItems[busyItems.length - 1]; // 兜底
607
611
  }
608
612
 
609
613
  function isMatchTarget(target, node, port) {
package/deps/util.js CHANGED
@@ -1608,27 +1608,39 @@ function ei(cmd, args = [], shell = false) {
1608
1608
  spawnSync(cmd, args, {stdio:"inherit", shell});
1609
1609
  }
1610
1610
 
1611
- async function eia(cmd, args = [], shell = false) {
1612
- `
1613
- 当前进程不会卡住,输入输出由cmd进程持有
1611
+ async function eia(cmd, args = [], shell = false, input = null) {
1614
1612
  `
1613
+ 当前进程不会卡住(事件循环仍在),但会 await 等子进程退出;
1614
+ 输入输出默认由 cmd 进程持有;如果传 input,则把 input 写入 stdin。
1615
+ `
1615
1616
  if (isRunningInBackground()) {
1616
1617
  throw 'Unsupported Operation';
1617
1618
  }
1618
1619
  setting.enableNextLine = false;
1619
- let child = spawn(cmd, args, {stdio:"inherit", shell});
1620
+
1621
+ // 如果需要写入 input,则 stdin 必须是 pipe
1622
+ const stdio = input != null
1623
+ ? ['pipe', 'inherit', 'inherit']
1624
+ : 'inherit';
1625
+
1626
+ const child = spawn(cmd, args, { stdio, shell });
1627
+
1628
+ // 把内存内容喂给子进程
1629
+ if (input != null) {
1630
+ child.stdin.write(input);
1631
+ child.stdin.end();
1632
+ }
1633
+
1620
1634
  return new Promise((resolve, reject) => {
1621
- // 监听子进程的关闭事件
1622
1635
  child.on('close', (code) => {
1623
1636
  setting.enableNextLine = true;
1624
1637
  resolve(code);
1625
1638
  });
1626
- // 可选:监听子进程的错误事件
1627
1639
  child.on('error', (err) => {
1628
1640
  setting.enableNextLine = true;
1629
- reject(err)
1641
+ reject(err);
1630
1642
  });
1631
- })
1643
+ });
1632
1644
  }
1633
1645
 
1634
1646
  async function getCbText(mbNum) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "3.0.9",
3
+ "version": "3.1.2",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {