jsir 3.0.0 → 3.0.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/cmd/oaa.js CHANGED
@@ -351,6 +351,8 @@ function initRl(callback, promptStr, hidden, reject) {
351
351
  _rl.clearLine(0)
352
352
  if (callback === wrapperInput) {
353
353
  nextLine();
354
+ } else {
355
+ closeRl()
354
356
  }
355
357
  }
356
358
  });
@@ -1128,23 +1130,24 @@ async function showRooms() {
1128
1130
  for (let i = 0; i < setting.rooms.length; i++) {
1129
1131
  let room = setting.rooms[i]
1130
1132
  let isLocal = setting.selfRoom.selfNode === room.selfNode;
1133
+ let roomName = room.active ? infoStr(room.name):room.name;
1134
+ let delayStr = vl(room.delay) ? (room.delay + "ms"):"";
1131
1135
  results.push({
1132
- name: (isLocal ? "*" : " ") + room.name,
1136
+ name: (isLocal ? infoStr("*") : " ") + roomName,
1133
1137
  node: room.selfNode,
1134
- active: room.active,
1138
+ delay: delayStr
1135
1139
  })
1136
1140
  for (let key of Object.keys(room.jsirs)) {
1137
1141
  let jsir = room.jsirs[key]
1138
- let pidStr = (process.pid === jsir.pid ? "*" : " ") + jsir.pid;
1142
+ let pidStr = (process.pid === jsir.pid ? infoStr("*") : " ") + (jsir.newError ? errorStr(jsir.pid):(jsir.active ? infoStr(jsir.pid):jsir.pid));
1139
1143
  results.push({
1140
- name: (isLocal ? "*" : " ") + room.name,
1144
+ name: (isLocal ? infoStr("*") : " ") + roomName,
1141
1145
  node: room.selfNode,
1142
- active: room.active,
1143
- pid: jsir.newError ? errorStr(pidStr):pidStr,
1146
+ delay: delayStr,
1147
+ pid: pidStr,
1144
1148
  up: formatSec(jsir.upTime) || '',
1145
1149
  version: jsir.version || '',
1146
1150
  space: jsir.space,
1147
- running: jsir.active,
1148
1151
  port: jsir.port,
1149
1152
  back: jsir.back,
1150
1153
  busy: jsir.busy,
@@ -1320,12 +1323,22 @@ const keywordDef = {
1320
1323
  console.msg("config service offline")
1321
1324
  } else if (_cmdMap[args[0]]){
1322
1325
  let uniqueName = _cmdMap[args[0]];
1323
- await eia(getEditor(), [`"${getConfigDir()}/${md5(uniqueName + (global.$TEST ? '.test':''))}.json"`], true)
1326
+ let configPath = `${getConfigDir()}/${md5(uniqueName + (global.$TEST ? '.test':''))}.json`;
1327
+ if (isRunningInBackground()) {
1328
+ console.log(String(await fp.readFile(configPath)).trim())
1329
+ } else {
1330
+ await eia(getEditor(), [`"${configPath}"`], true)
1331
+ }
1324
1332
  } else {
1325
1333
  console.warn('invalid args')
1326
1334
  }
1327
1335
  } else {
1328
- await eia(getEditor(), [`"${getLibDataDir()}/config.json"`], true)
1336
+ let configPath = `${getLibDataDir()}/config.json`;
1337
+ if (isRunningInBackground()) {
1338
+ console.log(String(await fp.readFile(configPath)).trim())
1339
+ } else {
1340
+ await eia(getEditor(), [`"${configPath}"`], true)
1341
+ }
1329
1342
  }
1330
1343
  },
1331
1344
  short: 's'
@@ -1703,6 +1716,10 @@ const keywordDef = {
1703
1716
  if (setting.selfRoom.selfNode === room.selfNode && String(process.pid) === pid) {
1704
1717
  continue;
1705
1718
  }
1719
+ if (setting.selfRoom.selfNode !== room.selfNode && args.includes(room.selfNode) && !args.includes(pid)
1720
+ && room.jsirs[pid].port === setting.defaultPort) {
1721
+ continue;
1722
+ }
1706
1723
  have = true;
1707
1724
  tasks.push(async (input) => {
1708
1725
  let jsir = room.jsirs[pid];
package/deps/room.js CHANGED
@@ -3,7 +3,7 @@ const {fileJson, fileLock, vl, getKeyTips, getValTips,
3
3
  getRoomsDir, e, isRunningInBackground,
4
4
  batchAsync, trim, getOr, errorTag, warnStr, getConfig, getConfigDir,
5
5
  fileExist, processLock, isPidAlive, cleanFileLocks,
6
- roomConsole: console
6
+ roomConsole: console, reget
7
7
  } = require('./util');
8
8
  const {setRoute, createSign} = require('../deps/server')
9
9
  const roomDataFile = "jsirRoom.json"
@@ -17,7 +17,6 @@ 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 defTasks = getConfig("tasks");
21
20
 
22
21
  async function localConfigs() {
23
22
  let configDir = getConfigDir();
@@ -161,6 +160,7 @@ async function syncRooms() {
161
160
  fns.push(async () => {
162
161
  let respBody = ''
163
162
  try {
163
+ let begin = Date.now();
164
164
  try {
165
165
  respBody = await reqNode(node, "get", "/");
166
166
  } catch (e) {
@@ -178,6 +178,7 @@ async function syncRooms() {
178
178
  Object.entries(currRoom.jsirs || {}).filter(([pid, jsir]) => jsir.port === setting.defaultPort)
179
179
  );
180
180
  }
181
+ currRoom.delay = Date.now() - begin;
181
182
  syncRooms.push(currRoom)
182
183
  console.$debug(`sync ${node} success`);
183
184
  }
@@ -272,32 +273,45 @@ async function _syncSetting(room) {
272
273
  }
273
274
  }
274
275
 
275
- async function processTasks() {
276
+ async function processTasks(defTasks) {
276
277
  await fileJson(roomTasksFile, async tasks => {
277
- tasks = Object.fromEntries(
278
- Object.entries(tasks).filter(([key, pid]) => isPidAlive(pid))
279
- );
280
- if (Object.values(tasks).includes(process.pid)) {
281
- return tasks;
278
+ for (let key of Object.keys(tasks)) {
279
+ let pids = tasks[key] || []
280
+ // 清理已经结束的进程
281
+ for (let i = 0; i < pids.length; i++) {
282
+ let pid = pids[i];
283
+ if (!isPidAlive(pid)) {
284
+ pids.splice(i, 1);
285
+ }
286
+ }
287
+ if (pids.length === 0) {
288
+ delete tasks[key]
289
+ }
282
290
  }
291
+
283
292
  let unHandleKey = null;
284
293
  for (let key of Object.keys(defTasks)) {
285
- if (!tasks[key]) {
286
- if (key.indexOf("*") !== -1 && setting.defaultPort !== setting.selfJsir.port) {
287
- continue;
288
- }
289
- if (key.indexOf("*") === -1 && setting.defaultPort === setting.selfJsir.port) {
290
- continue;
291
- }
292
- unHandleKey = key
293
- break;
294
+ let isMainPid = setting.defaultPort === setting.selfJsir.port;
295
+ let isMainTask = key.includes("*");
296
+ if (isMainPid !== isMainTask) {
297
+ continue;
298
+ }
299
+
300
+ let num = Number(reget(trim(key), /(\d+)$/) || 1);
301
+ let taskKey = trim(trim(key).replace(/\d+$/, ''));
302
+ let pids = tasks[taskKey] || [];
303
+ if (pids.length >= num || pids.includes(process.pid)) {
304
+ continue;
294
305
  }
306
+
307
+ unHandleKey = key;
295
308
  }
296
309
  if (unHandleKey) {
297
310
  console.$log(process.pid, `run task ${unHandleKey}[${defTasks[unHandleKey]}]`)
298
311
  await setting.wrapperInput(defTasks[unHandleKey]);
299
312
  if (!setting.newError) {
300
- tasks[unHandleKey] = process.pid;
313
+ let taskKey = trim(trim(unHandleKey).replace(/\d+$/, ''));
314
+ tasks[taskKey] = [...(tasks[taskKey] || []), process.pid];
301
315
  console.$log(process.pid, `handle task ${unHandleKey}[${defTasks[unHandleKey]}]`)
302
316
  }
303
317
  }
@@ -329,8 +343,9 @@ async function initRoom() {
329
343
  await Promise.all(pros);
330
344
  }, false).catch(console.$debug)
331
345
  }
346
+ const defTasks = getConfig("tasks");
332
347
  if (defTasks && Object.keys(defTasks).length > 0) {
333
- processLock(roomTasksFile, processTasks, false).catch(console.$debug)
348
+ processLock(roomTasksFile, () => processTasks(defTasks), false).catch(console.$debug)
334
349
  }
335
350
  await syncSetting();
336
351
  }
@@ -353,11 +368,11 @@ async function syncConfigs() {
353
368
  let currText = String(await fp.readFile(path));
354
369
  if (currText !== text) {
355
370
  await fp.writeFile(path, text)
356
- console.$debug(`sync ${key} success`);
371
+ console.$debug(`update config ${key} success`);
357
372
  }
358
373
  } else {
359
374
  await fp.writeFile(path, text)
360
- console.$debug(`sync ${key} success`);
375
+ console.$debug(`create config ${key} success`);
361
376
  }
362
377
  });
363
378
  }
@@ -520,10 +535,12 @@ async function reqNode(node, method, url, port, body) {
520
535
  });
521
536
 
522
537
  // 设置超时逻辑
523
- if (setting.reqNodeTimeouts[url]) {
538
+ let timeoutMs = setting.reqNodeTimeouts[url];
539
+ if (timeoutMs) {
524
540
  timeout = setTimeout(() => {
525
541
  req.destroy(); // 中断请求
526
- }, setting.reqNodeTimeouts[url]); // 10秒超时
542
+ reject(new Error(`Timeout ${timeoutMs}ms`))
543
+ }, timeoutMs); // 10秒超时
527
544
  }
528
545
 
529
546
  // 错误处理
package/deps/util.js CHANGED
@@ -844,7 +844,8 @@ function createLimitLogger(fileName, {
844
844
  setting.newError = true;
845
845
  }
846
846
  if (time) {
847
- text = `${timeStr('YYYY-MM-DD HH:mm:ss.SSS')} ${String(process.pid%1000).padStart(3, '0')}> ${text}`
847
+ let prefix = debugStr(`${timeStr('YYYY-MM-DD HH:mm:ss.SSS')} ${String(process.pid%1000).padStart(3, '0')}>`)
848
+ text = `${prefix} ${text}`
848
849
  }
849
850
  fp.appendFile(logPath, text + '\n')
850
851
  let _minNum = (Date.now()/(1000 * 60 * 10)).toFixed(0)
@@ -1435,33 +1436,28 @@ function setTips(key, value, onRm) {
1435
1436
  }
1436
1437
  }
1437
1438
 
1438
- function delTips(...keys) {
1439
+ async function delTips(...keys) {
1439
1440
  keys = keys.map(trim).filter(i => i)
1440
- let pros = []
1441
- for (let key of Object.keys(setting.tips)) {
1441
+ for (let key of Object.keys(setting.tips).reverse()) {
1442
1442
  if (keys.length === 0) {
1443
1443
  if (['TEST', 'DEBUG'].includes(key)) {
1444
1444
  continue
1445
1445
  }
1446
1446
  delete setting.tips[key]
1447
- pros.push(tipsOnRmCallback(key))
1447
+ await tipsOnRmCallback(key)
1448
1448
  } else if (keys.indexOf(key) !== -1) {
1449
1449
  delete setting.tips[key]
1450
- pros.push(tipsOnRmCallback(key))
1450
+ await tipsOnRmCallback(key)
1451
1451
  }
1452
1452
  }
1453
1453
  if (keys.length === 0) {
1454
- for (let key of Object.keys(setting.tipsOnRm)) {
1454
+ for (let key of Object.keys(setting.tipsOnRm).reverse()) {
1455
1455
  if (['TEST', 'DEBUG'].includes(key)) {
1456
1456
  continue
1457
1457
  }
1458
- pros.push(tipsOnRmCallback(key))
1458
+ await tipsOnRmCallback(key)
1459
1459
  }
1460
1460
  }
1461
- pros = pros.filter(i => i);
1462
- if (pros.length > 0) {
1463
- return Promise.all(pros)
1464
- }
1465
1461
  }
1466
1462
 
1467
1463
  function hasTips(key, value) {
@@ -1497,7 +1493,7 @@ function tipsOnRmCallback(key) {
1497
1493
  }
1498
1494
  }
1499
1495
  if (pros.length > 0) {
1500
- return Promise.all(pros);
1496
+ return Promise.all(pros);
1501
1497
  }
1502
1498
  }
1503
1499
 
@@ -1532,8 +1528,12 @@ async function cleanFile(path, maxChars = 9 * 1024 * 1024) {
1532
1528
  }
1533
1529
 
1534
1530
  function isPidAlive(pid) {
1531
+ pid = Number(pid);
1532
+ if (process.pid === pid) {
1533
+ return true;
1534
+ }
1535
1535
  try {
1536
- process.kill(Number(pid), 0); // 信号 0 不会实际发送,但会检查进程是否存在
1536
+ process.kill(pid, 0); // 信号 0 不会实际发送,但会检查进程是否存在
1537
1537
  return true; // PID 存在
1538
1538
  } catch (err) {
1539
1539
  if (err.code === 'ESRCH') {
@@ -2100,6 +2100,9 @@ function getValTips() {
2100
2100
  }
2101
2101
  }
2102
2102
  let item = trim(i)
2103
+ if (item.startsWith("_")) {
2104
+ item = key;
2105
+ }
2103
2106
  if (item.indexOf(',') !== -1) {
2104
2107
  item = `[${item}]`;
2105
2108
  }
@@ -2233,6 +2236,18 @@ const tipFns = {
2233
2236
  key: tipKeys
2234
2237
  }
2235
2238
 
2239
+ function currentJsir() {
2240
+ return JSON.parse(JSON.stringify(setting.selfJsir));
2241
+ }
2242
+
2243
+ function currentRoom() {
2244
+ return JSON.parse(JSON.stringify(setting.selfRoom));
2245
+ }
2246
+
2247
+ function currentRooms() {
2248
+ return JSON.parse(JSON.stringify(setting.rooms));
2249
+ }
2250
+
2236
2251
  module.exports = {
2237
2252
  formatSec,
2238
2253
  wrapperJsirText,
@@ -2350,5 +2365,8 @@ module.exports = {
2350
2365
  tipFns,
2351
2366
  getFileOpenExe,
2352
2367
  roomConsole: createConsole(null, roomLog, roomError),
2353
- formatMb
2368
+ formatMb,
2369
+ currentJsir,
2370
+ currentRoom,
2371
+ currentRooms
2354
2372
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jsir",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "description": "JavaScript Script Management Tool",
5
5
  "main": "index.js",
6
6
  "scripts": {