lnlink-server 1.1.2 → 1.1.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/app.js +312 -312
- package/dist/build-info.json +1 -1
- package/dist/index.js +267 -168
- package/dist/index.js.map +2 -2
- package/dist/package.json +1 -1
- package/dist/public/css/initOwner.css +7 -0
- package/dist/public/js/init.js +366 -357
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -122,6 +122,15 @@ var require_linkLogger = __commonJS({
|
|
|
122
122
|
}
|
|
123
123
|
// Cache for logger instances to avoid creating multiple instances with the same logType
|
|
124
124
|
static instances = /* @__PURE__ */ new Map();
|
|
125
|
+
// Silent mode flag - when true, all logging is suppressed (used during graceful shutdown)
|
|
126
|
+
static silentMode = false;
|
|
127
|
+
/**
|
|
128
|
+
* Set silent mode to suppress all logging (used during graceful shutdown)
|
|
129
|
+
* @param {boolean} value - Whether to enable silent mode
|
|
130
|
+
*/
|
|
131
|
+
static setSilentMode(value) {
|
|
132
|
+
_Logger.silentMode = value;
|
|
133
|
+
}
|
|
125
134
|
constructor(logType) {
|
|
126
135
|
if (_Logger.instances.has(logType)) {
|
|
127
136
|
return _Logger.instances.get(logType);
|
|
@@ -131,21 +140,27 @@ var require_linkLogger = __commonJS({
|
|
|
131
140
|
_Logger.instances.set(logType, this);
|
|
132
141
|
}
|
|
133
142
|
debug(message, ...args) {
|
|
143
|
+
if (_Logger.silentMode) return;
|
|
134
144
|
this.logger.debug({ msg: message }, ...args);
|
|
135
145
|
}
|
|
136
146
|
info(message, ...args) {
|
|
147
|
+
if (_Logger.silentMode) return;
|
|
137
148
|
this.logger.info({ msg: message }, ...args);
|
|
138
149
|
}
|
|
139
150
|
warn(message, ...args) {
|
|
151
|
+
if (_Logger.silentMode) return;
|
|
140
152
|
this.logger.warn({ msg: message }, ...args);
|
|
141
153
|
}
|
|
142
154
|
error(message, ...args) {
|
|
155
|
+
if (_Logger.silentMode) return;
|
|
143
156
|
this.logger.error({ msg: message }, ...args);
|
|
144
157
|
}
|
|
145
158
|
fatal(message, ...args) {
|
|
159
|
+
if (_Logger.silentMode) return;
|
|
146
160
|
this.logger.fatal({ msg: message }, ...args);
|
|
147
161
|
}
|
|
148
162
|
logWithData(level, message, data) {
|
|
163
|
+
if (_Logger.silentMode) return;
|
|
149
164
|
this.logger[level]({ ...data, msg: message });
|
|
150
165
|
}
|
|
151
166
|
};
|
|
@@ -2720,7 +2735,6 @@ var require_getConfig = __commonJS({
|
|
|
2720
2735
|
"LINK_DEBUG",
|
|
2721
2736
|
"LINK_ENABLE_TOR",
|
|
2722
2737
|
"LINK_NODE_ENV",
|
|
2723
|
-
"LINK_AUTO_ASSIGN_PORTS",
|
|
2724
2738
|
"LINK_HTTPS_PROXY",
|
|
2725
2739
|
"LINK_DATABASE_URL",
|
|
2726
2740
|
"LINK_REPORT_BASE_URL",
|
|
@@ -2885,9 +2899,7 @@ var require_getConfig = __commonJS({
|
|
|
2885
2899
|
combinedConfig.LINK_TOR_SOCKS_PORT = combinedConfig.LINK_TOR_SOCKS_PORT || 9050;
|
|
2886
2900
|
combinedConfig.LINK_TOR_CONTROL_PORT = combinedConfig.LINK_TOR_CONTROL_PORT || 9051;
|
|
2887
2901
|
try {
|
|
2888
|
-
|
|
2889
|
-
combinedConfig = await assignAvailablePorts(combinedConfig);
|
|
2890
|
-
}
|
|
2902
|
+
combinedConfig = await assignAvailablePorts(combinedConfig);
|
|
2891
2903
|
} catch (portError) {
|
|
2892
2904
|
console.warn(
|
|
2893
2905
|
"Port assignment failed, using default ports:",
|
|
@@ -5577,7 +5589,6 @@ var require_processManager = __commonJS({
|
|
|
5577
5589
|
"business/service/nodeManage/processManager.js"(exports2, module2) {
|
|
5578
5590
|
var { spawn } = require("node:child_process");
|
|
5579
5591
|
var findProcess = require("find-process").default;
|
|
5580
|
-
var { getLightningService } = require_common();
|
|
5581
5592
|
var { getConfig: getConfig2 } = require_getConfig();
|
|
5582
5593
|
var Logger = require_linkLogger();
|
|
5583
5594
|
var { sleep } = require_timeUtils();
|
|
@@ -5587,6 +5598,11 @@ var require_processManager = __commonJS({
|
|
|
5587
5598
|
return config.LINK_EXTERNAL_NODES === "true" || config.LINK_EXTERNAL_NODES === true;
|
|
5588
5599
|
}
|
|
5589
5600
|
__name(isExternalNodesMode, "isExternalNodesMode");
|
|
5601
|
+
function shouldDetach() {
|
|
5602
|
+
const config = getConfig2();
|
|
5603
|
+
return config.LINK_NODE_ENV !== "app";
|
|
5604
|
+
}
|
|
5605
|
+
__name(shouldDetach, "shouldDetach");
|
|
5590
5606
|
function terminateProcess(pid, force = false) {
|
|
5591
5607
|
const logger2 = new Logger("processManager");
|
|
5592
5608
|
try {
|
|
@@ -5601,9 +5617,19 @@ var require_processManager = __commonJS({
|
|
|
5601
5617
|
}
|
|
5602
5618
|
__name(terminateProcess, "terminateProcess");
|
|
5603
5619
|
var serviceState = {
|
|
5604
|
-
services: null
|
|
5620
|
+
services: null,
|
|
5605
5621
|
// Will be initialized when needed
|
|
5622
|
+
isShuttingDown: false
|
|
5623
|
+
// Flag to suppress async logs during shutdown
|
|
5606
5624
|
};
|
|
5625
|
+
function setShuttingDown(value) {
|
|
5626
|
+
serviceState.isShuttingDown = value;
|
|
5627
|
+
}
|
|
5628
|
+
__name(setShuttingDown, "setShuttingDown");
|
|
5629
|
+
function isShuttingDown() {
|
|
5630
|
+
return serviceState.isShuttingDown;
|
|
5631
|
+
}
|
|
5632
|
+
__name(isShuttingDown, "isShuttingDown");
|
|
5607
5633
|
function initializeServices() {
|
|
5608
5634
|
if (!serviceState.services) {
|
|
5609
5635
|
serviceState.services = getServiceConfig();
|
|
@@ -5654,7 +5680,8 @@ var require_processManager = __commonJS({
|
|
|
5654
5680
|
}
|
|
5655
5681
|
}, "settleReject");
|
|
5656
5682
|
const proc = spawn(service.command, args, {
|
|
5657
|
-
stdio: "pipe"
|
|
5683
|
+
stdio: "pipe",
|
|
5684
|
+
detached: shouldDetach()
|
|
5658
5685
|
});
|
|
5659
5686
|
setServiceProcess("litd", proc);
|
|
5660
5687
|
timeoutId = setTimeout(() => {
|
|
@@ -5664,7 +5691,9 @@ var require_processManager = __commonJS({
|
|
|
5664
5691
|
}
|
|
5665
5692
|
}, LITD_STARTUP_TIMEOUT);
|
|
5666
5693
|
proc.once("exit", (code, signal) => {
|
|
5667
|
-
|
|
5694
|
+
if (!isShuttingDown()) {
|
|
5695
|
+
logger2.info(`litd process exited with code ${code ?? "null"}, signal ${signal ?? "null"}`);
|
|
5696
|
+
}
|
|
5668
5697
|
const currentService = getService("litd");
|
|
5669
5698
|
if (currentService?.process === proc) {
|
|
5670
5699
|
setServiceProcess("litd", null);
|
|
@@ -5727,7 +5756,8 @@ var require_processManager = __commonJS({
|
|
|
5727
5756
|
}, "settleReject");
|
|
5728
5757
|
logger2.info(`Tor config: ${JSON.stringify(args, null, 2)}`);
|
|
5729
5758
|
const proc = spawn(service.command, args, {
|
|
5730
|
-
stdio: "pipe"
|
|
5759
|
+
stdio: "pipe",
|
|
5760
|
+
detached: shouldDetach()
|
|
5731
5761
|
});
|
|
5732
5762
|
setServiceProcess("tor", proc);
|
|
5733
5763
|
timeoutId = setTimeout(() => {
|
|
@@ -5737,7 +5767,9 @@ var require_processManager = __commonJS({
|
|
|
5737
5767
|
}
|
|
5738
5768
|
}, TOR_STARTUP_TIMEOUT);
|
|
5739
5769
|
proc.once("exit", (code, signal) => {
|
|
5740
|
-
|
|
5770
|
+
if (!isShuttingDown()) {
|
|
5771
|
+
logger2.info(`tor process exited with code ${code ?? "null"}, signal ${signal ?? "null"}`);
|
|
5772
|
+
}
|
|
5741
5773
|
const currentService = getService("tor");
|
|
5742
5774
|
if (currentService?.process === proc) {
|
|
5743
5775
|
setServiceProcess("tor", null);
|
|
@@ -5805,7 +5837,8 @@ var require_processManager = __commonJS({
|
|
|
5805
5837
|
}
|
|
5806
5838
|
}, "settleReject");
|
|
5807
5839
|
const proc = spawn(service.command, args, {
|
|
5808
|
-
stdio: "pipe"
|
|
5840
|
+
stdio: "pipe",
|
|
5841
|
+
detached: shouldDetach()
|
|
5809
5842
|
});
|
|
5810
5843
|
setServiceProcess("rgb", proc);
|
|
5811
5844
|
timeoutId = setTimeout(() => {
|
|
@@ -5815,7 +5848,9 @@ var require_processManager = __commonJS({
|
|
|
5815
5848
|
}
|
|
5816
5849
|
}, RGB_STARTUP_TIMEOUT);
|
|
5817
5850
|
proc.once("exit", (code, signal) => {
|
|
5818
|
-
|
|
5851
|
+
if (!isShuttingDown()) {
|
|
5852
|
+
logger2.info(`rgb process exited with code ${code ?? "null"}, signal ${signal ?? "null"}`);
|
|
5853
|
+
}
|
|
5819
5854
|
const currentService = getService("rgb");
|
|
5820
5855
|
if (currentService?.process === proc) {
|
|
5821
5856
|
setServiceProcess("rgb", null);
|
|
@@ -5923,35 +5958,12 @@ var require_processManager = __commonJS({
|
|
|
5923
5958
|
const trackedProcess = initialService.process;
|
|
5924
5959
|
const processAlive = trackedProcess && !trackedProcess.killed && trackedProcess.exitCode === null;
|
|
5925
5960
|
if (processAlive) {
|
|
5926
|
-
|
|
5927
|
-
|
|
5928
|
-
const lightningService = getLightningService();
|
|
5929
|
-
await lightningService.stopDaemon();
|
|
5930
|
-
logger2.info("LND daemon stopped gracefully via RPC");
|
|
5931
|
-
let waitCount = 0;
|
|
5932
|
-
const maxWait = 10;
|
|
5933
|
-
while (waitCount < maxWait) {
|
|
5934
|
-
const currentProcess = getService("litd")?.process ?? trackedProcess;
|
|
5935
|
-
if (!currentProcess || currentProcess.killed || currentProcess.exitCode !== null) {
|
|
5936
|
-
setServiceProcess("litd", null);
|
|
5937
|
-
return true;
|
|
5938
|
-
}
|
|
5939
|
-
await sleep(1e3);
|
|
5940
|
-
waitCount++;
|
|
5941
|
-
}
|
|
5942
|
-
logger2.warn("Process did not exit after RPC shutdown, proceeding with fallback...");
|
|
5943
|
-
} catch (error) {
|
|
5944
|
-
logger2.warn(`RPC shutdown failed: ${error.message}, falling back to process termination`);
|
|
5945
|
-
}
|
|
5946
|
-
} else {
|
|
5947
|
-
logger2.info("litd process already exited, skipping RPC shutdown");
|
|
5948
|
-
setServiceProcess("litd", null);
|
|
5949
|
-
}
|
|
5950
|
-
const fallbackService = getService("litd") ?? initialService;
|
|
5951
|
-
if (fallbackService.process) {
|
|
5952
|
-
return await killProcess(fallbackService.process, "litd");
|
|
5961
|
+
logger2.info("Stopping litd via SIGTERM...");
|
|
5962
|
+
return await killProcess(trackedProcess, "litd", 5e3);
|
|
5953
5963
|
}
|
|
5954
|
-
|
|
5964
|
+
logger2.info("litd process already exited, cleaning up...");
|
|
5965
|
+
setServiceProcess("litd", null);
|
|
5966
|
+
return await findAndKillProcess(initialService.command, "litd");
|
|
5955
5967
|
}
|
|
5956
5968
|
__name(stopLitdService, "stopLitdService");
|
|
5957
5969
|
async function stopTorService() {
|
|
@@ -6007,32 +6019,12 @@ var require_processManager = __commonJS({
|
|
|
6007
6019
|
if (!service) {
|
|
6008
6020
|
throw new Error("rgb service not found");
|
|
6009
6021
|
}
|
|
6010
|
-
try {
|
|
6011
|
-
logger2.info("Attempting graceful shutdown of RGB via SIGTERM...");
|
|
6012
|
-
const processList = await findProcess("name", "rgb-lightning-node");
|
|
6013
|
-
if (processList.length > 0) {
|
|
6014
|
-
processList.forEach((p) => terminateProcess(p.pid, false));
|
|
6015
|
-
await sleep(2e3);
|
|
6016
|
-
setServiceProcess("rgb", null);
|
|
6017
|
-
const remaining = await findProcess("name", "rgb-lightning-node");
|
|
6018
|
-
if (remaining.length === 0) {
|
|
6019
|
-
logger2.info("RGB stopped gracefully");
|
|
6020
|
-
return true;
|
|
6021
|
-
}
|
|
6022
|
-
logger2.warn(`${remaining.length} RGB process(es) still running after SIGTERM, force killing...`);
|
|
6023
|
-
remaining.forEach((p) => terminateProcess(p.pid, true));
|
|
6024
|
-
setServiceProcess("rgb", null);
|
|
6025
|
-
return true;
|
|
6026
|
-
}
|
|
6027
|
-
logger2.info("No RGB processes found via find-process, trying tracked process...");
|
|
6028
|
-
} catch (error) {
|
|
6029
|
-
logger2.warn(`RGB graceful shutdown failed: ${error.message}, falling back to process termination`);
|
|
6030
|
-
}
|
|
6031
6022
|
if (service.process) {
|
|
6032
|
-
|
|
6033
|
-
|
|
6034
|
-
return await findAndKillProcess("rgb-lightning-node", "rgb");
|
|
6023
|
+
logger2.info("Stopping RGB via tracked process...");
|
|
6024
|
+
return await killProcess(service.process, "rgb", 5e3);
|
|
6035
6025
|
}
|
|
6026
|
+
logger2.info("No tracked RGB process, falling back to system scan...");
|
|
6027
|
+
return await findAndKillProcess("rgb-lightning-node", "rgb");
|
|
6036
6028
|
}
|
|
6037
6029
|
__name(stopRgbService, "stopRgbService");
|
|
6038
6030
|
async function stopService(name) {
|
|
@@ -6079,13 +6071,24 @@ var require_processManager = __commonJS({
|
|
|
6079
6071
|
};
|
|
6080
6072
|
}
|
|
6081
6073
|
__name(getServicesState, "getServicesState");
|
|
6074
|
+
function getServicePids() {
|
|
6075
|
+
const services = initializeServices();
|
|
6076
|
+
return {
|
|
6077
|
+
litd: services.litd?.process?.pid || null,
|
|
6078
|
+
tor: services.tor?.process?.pid || null,
|
|
6079
|
+
rgb: services.rgb?.process?.pid || null
|
|
6080
|
+
};
|
|
6081
|
+
}
|
|
6082
|
+
__name(getServicePids, "getServicePids");
|
|
6082
6083
|
module2.exports = {
|
|
6083
6084
|
startService,
|
|
6084
6085
|
stopService,
|
|
6085
6086
|
stopLitdService,
|
|
6086
6087
|
stopTorService,
|
|
6087
6088
|
stopRgbService,
|
|
6088
|
-
getServicesState
|
|
6089
|
+
getServicesState,
|
|
6090
|
+
getServicePids,
|
|
6091
|
+
setShuttingDown
|
|
6089
6092
|
};
|
|
6090
6093
|
}
|
|
6091
6094
|
});
|
|
@@ -6202,21 +6205,11 @@ var require_node = __commonJS({
|
|
|
6202
6205
|
tag: TASKS.EnableRGBNode
|
|
6203
6206
|
});
|
|
6204
6207
|
}
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
const status = await getNodeState();
|
|
6211
|
-
resolve({
|
|
6212
|
-
message: "Request submitted, current node status:",
|
|
6213
|
-
status
|
|
6214
|
-
});
|
|
6215
|
-
}, timeoutMs);
|
|
6216
|
-
});
|
|
6217
|
-
const result = await Promise.race([unlockPromise, timeoutPromise]);
|
|
6218
|
-
clearTimeout(timeoutId);
|
|
6219
|
-
return result || true;
|
|
6208
|
+
rgbClient.node.unlockNode(unlockNodeParams).then(() => {
|
|
6209
|
+
}).catch((err) => console.error("[rgb] unlockNode background error:", err.message));
|
|
6210
|
+
const linkCache = require_linkCache();
|
|
6211
|
+
linkCache.set("rgbState", 3);
|
|
6212
|
+
return { state: 3, message: "Unlock submitted, syncing..." };
|
|
6220
6213
|
}
|
|
6221
6214
|
__name(unlockNode, "unlockNode");
|
|
6222
6215
|
async function backupNode({ password }) {
|
|
@@ -6276,6 +6269,7 @@ var require_statusChecker = __commonJS({
|
|
|
6276
6269
|
var { getNodeState } = require_node();
|
|
6277
6270
|
var { getServiceConfig } = require_config2();
|
|
6278
6271
|
var { getServicesState } = require_processManager();
|
|
6272
|
+
var normalizePath = /* @__PURE__ */ __name((s) => s ? s.replace(/\\/g, "/") : "", "normalizePath");
|
|
6279
6273
|
function isExternalNodesMode() {
|
|
6280
6274
|
const config = getConfig2();
|
|
6281
6275
|
return config.LINK_EXTERNAL_NODES === "true" || config.LINK_EXTERNAL_NODES === true;
|
|
@@ -6313,10 +6307,26 @@ var require_statusChecker = __commonJS({
|
|
|
6313
6307
|
}
|
|
6314
6308
|
return ServiceStatus.STOPPED;
|
|
6315
6309
|
}
|
|
6310
|
+
const { LINK_DATA_PATH } = getConfig2();
|
|
6316
6311
|
const processList = await findProcess("name", "litd");
|
|
6312
|
+
if (!LINK_DATA_PATH) {
|
|
6313
|
+
if (processList.length > 0) {
|
|
6314
|
+
logger2.warn("LINK_DATA_PATH not set, cannot filter litd by ownership. Returning RUNNING based on process name match.");
|
|
6315
|
+
return ServiceStatus.RUNNING;
|
|
6316
|
+
}
|
|
6317
|
+
return ServiceStatus.STOPPED;
|
|
6318
|
+
}
|
|
6319
|
+
const lnlinkLitdDataDir = `${LINK_DATA_PATH}/.litd`;
|
|
6317
6320
|
if (processList.length > 0) {
|
|
6318
|
-
|
|
6319
|
-
|
|
6321
|
+
const targetDir = normalizePath(lnlinkLitdDataDir);
|
|
6322
|
+
const lnlinkLitdProcess = processList.find((p) => p.cmd && normalizePath(p.cmd).includes(targetDir));
|
|
6323
|
+
if (lnlinkLitdProcess) {
|
|
6324
|
+
logger2.info(`Found lnlink litd process: PID ${lnlinkLitdProcess.pid}`);
|
|
6325
|
+
return ServiceStatus.RUNNING;
|
|
6326
|
+
} else {
|
|
6327
|
+
logger2.debug(`Found ${processList.length} litd process(es), but none belong to lnlink (data dir: ${lnlinkLitdDataDir})`);
|
|
6328
|
+
return ServiceStatus.STOPPED;
|
|
6329
|
+
}
|
|
6320
6330
|
}
|
|
6321
6331
|
return ServiceStatus.STOPPED;
|
|
6322
6332
|
} catch (error) {
|
|
@@ -6341,10 +6351,26 @@ var require_statusChecker = __commonJS({
|
|
|
6341
6351
|
}
|
|
6342
6352
|
return ServiceStatus.STOPPED;
|
|
6343
6353
|
}
|
|
6354
|
+
const { LINK_DATA_PATH } = getConfig2();
|
|
6344
6355
|
const processList = await findProcess("name", "rgb-lightning-node");
|
|
6356
|
+
if (!LINK_DATA_PATH) {
|
|
6357
|
+
if (processList.length > 0) {
|
|
6358
|
+
logger2.warn("LINK_DATA_PATH not set, cannot filter RGB by ownership. Returning RUNNING based on process name match.");
|
|
6359
|
+
return ServiceStatus.RUNNING;
|
|
6360
|
+
}
|
|
6361
|
+
return ServiceStatus.STOPPED;
|
|
6362
|
+
}
|
|
6363
|
+
const lnlinkRgbDataDir = `${LINK_DATA_PATH}/.rgb`;
|
|
6345
6364
|
if (processList.length > 0) {
|
|
6346
|
-
|
|
6347
|
-
|
|
6365
|
+
const targetDir = normalizePath(lnlinkRgbDataDir);
|
|
6366
|
+
const lnlinkRgbProcess = processList.find((p) => p.cmd && normalizePath(p.cmd).includes(targetDir));
|
|
6367
|
+
if (lnlinkRgbProcess) {
|
|
6368
|
+
logger2.info(`Found lnlink RGB process: PID ${lnlinkRgbProcess.pid}`);
|
|
6369
|
+
return ServiceStatus.RUNNING;
|
|
6370
|
+
} else {
|
|
6371
|
+
logger2.debug(`Found ${processList.length} rgb-lightning-node process(es), but none belong to lnlink (data dir: ${lnlinkRgbDataDir})`);
|
|
6372
|
+
return ServiceStatus.STOPPED;
|
|
6373
|
+
}
|
|
6348
6374
|
}
|
|
6349
6375
|
return ServiceStatus.STOPPED;
|
|
6350
6376
|
} catch (error) {
|
|
@@ -6383,12 +6409,25 @@ var require_statusChecker = __commonJS({
|
|
|
6383
6409
|
}
|
|
6384
6410
|
}
|
|
6385
6411
|
__name(checkProcess, "checkProcess");
|
|
6386
|
-
|
|
6387
|
-
|
|
6412
|
+
var terminalStatusCache = {
|
|
6413
|
+
data: null,
|
|
6414
|
+
timestamp: 0,
|
|
6415
|
+
TTL_MS: 5e3
|
|
6416
|
+
// 5 seconds cache
|
|
6417
|
+
};
|
|
6418
|
+
async function getTerminalStatus(filter = "") {
|
|
6388
6419
|
const logger2 = new Logger("statusChecker");
|
|
6420
|
+
if (!filter && terminalStatusCache.data) {
|
|
6421
|
+
const age = Date.now() - terminalStatusCache.timestamp;
|
|
6422
|
+
if (age < terminalStatusCache.TTL_MS) {
|
|
6423
|
+
logger2.debug(`getTerminalStatus: returning cached result (age: ${age}ms)`);
|
|
6424
|
+
return [...terminalStatusCache.data];
|
|
6425
|
+
}
|
|
6426
|
+
}
|
|
6427
|
+
const services = getServiceConfig();
|
|
6389
6428
|
const shouldInclude = /* @__PURE__ */ __name((name) => name !== "rgb" && (!filter || name.includes(filter)), "shouldInclude");
|
|
6390
6429
|
const filteredServices = Object.keys(services).filter(shouldInclude);
|
|
6391
|
-
|
|
6430
|
+
const result = await Promise.all(
|
|
6392
6431
|
filteredServices.map(async (name) => {
|
|
6393
6432
|
try {
|
|
6394
6433
|
const state = await checkProcess(name);
|
|
@@ -6403,8 +6442,18 @@ var require_statusChecker = __commonJS({
|
|
|
6403
6442
|
}
|
|
6404
6443
|
})
|
|
6405
6444
|
);
|
|
6445
|
+
if (!filter) {
|
|
6446
|
+
terminalStatusCache.data = result;
|
|
6447
|
+
terminalStatusCache.timestamp = Date.now();
|
|
6448
|
+
}
|
|
6449
|
+
return result;
|
|
6406
6450
|
}
|
|
6407
6451
|
__name(getTerminalStatus, "getTerminalStatus");
|
|
6452
|
+
function invalidateTerminalStatusCache() {
|
|
6453
|
+
terminalStatusCache.data = null;
|
|
6454
|
+
terminalStatusCache.timestamp = 0;
|
|
6455
|
+
}
|
|
6456
|
+
__name(invalidateTerminalStatusCache, "invalidateTerminalStatusCache");
|
|
6408
6457
|
async function getRGBStatus() {
|
|
6409
6458
|
const logger2 = new Logger("statusChecker");
|
|
6410
6459
|
try {
|
|
@@ -6461,6 +6510,7 @@ var require_statusChecker = __commonJS({
|
|
|
6461
6510
|
checkProcess,
|
|
6462
6511
|
getRGBStatus,
|
|
6463
6512
|
getTerminalStatus,
|
|
6513
|
+
invalidateTerminalStatusCache,
|
|
6464
6514
|
isServiceRunning,
|
|
6465
6515
|
waitForServiceStatus
|
|
6466
6516
|
};
|
|
@@ -6486,6 +6536,7 @@ var require_nodeManage = __commonJS({
|
|
|
6486
6536
|
var { startService, stopService } = require_processManager();
|
|
6487
6537
|
var {
|
|
6488
6538
|
getTerminalStatus,
|
|
6539
|
+
invalidateTerminalStatusCache,
|
|
6489
6540
|
isServiceRunning,
|
|
6490
6541
|
getRGBStatus,
|
|
6491
6542
|
ServiceStatus
|
|
@@ -6546,22 +6597,30 @@ var require_nodeManage = __commonJS({
|
|
|
6546
6597
|
return { matched: false, statuses: lastStatuses };
|
|
6547
6598
|
}
|
|
6548
6599
|
__name(waitForRgbStatus, "waitForRgbStatus");
|
|
6600
|
+
var isStartingTerminal = false;
|
|
6601
|
+
var isStartingRGB = false;
|
|
6549
6602
|
async function startTerminal({ waitForRunning = true } = {}) {
|
|
6550
6603
|
const logger2 = new Logger("litdService");
|
|
6551
|
-
|
|
6552
|
-
|
|
6553
|
-
|
|
6554
|
-
|
|
6555
|
-
|
|
6556
|
-
const torStatus = startStatus.find((item) => item.service_name === "tor");
|
|
6557
|
-
logger2.info(`Current status - Litd: ${litdStatus?.status}, Tor: ${torStatus?.status}`);
|
|
6558
|
-
let torSucceeded = !isStartTor;
|
|
6604
|
+
if (isStartingTerminal) {
|
|
6605
|
+
logger2.warn("Terminal start already in progress, returning current status");
|
|
6606
|
+
return await getTerminalStatus();
|
|
6607
|
+
}
|
|
6608
|
+
isStartingTerminal = true;
|
|
6559
6609
|
try {
|
|
6610
|
+
const { LINK_ENABLE_TOR } = getConfig2();
|
|
6611
|
+
const isStartTor = LINK_ENABLE_TOR === "true" || LINK_ENABLE_TOR === true;
|
|
6612
|
+
logger2.info("Starting terminal services...");
|
|
6613
|
+
const startStatus = await getTerminalStatus();
|
|
6614
|
+
const litdStatus = startStatus.find((item) => item.service_name === "litd");
|
|
6615
|
+
const torStatus = startStatus.find((item) => item.service_name === "tor");
|
|
6616
|
+
logger2.info(`Current status - Litd: ${litdStatus?.status}, Tor: ${torStatus?.status}`);
|
|
6617
|
+
let torSucceeded = !isStartTor;
|
|
6560
6618
|
if (isStartTor && torStatus?.status === ServiceStatus.STOPPED) {
|
|
6561
6619
|
logger2.info("Starting Tor service...");
|
|
6562
6620
|
try {
|
|
6563
6621
|
const torArgs = buildTorArgs();
|
|
6564
6622
|
await startService("tor", torArgs);
|
|
6623
|
+
invalidateTerminalStatusCache();
|
|
6565
6624
|
torSucceeded = true;
|
|
6566
6625
|
logger2.info("Tor service started successfully");
|
|
6567
6626
|
} catch (torError) {
|
|
@@ -6579,6 +6638,7 @@ var require_nodeManage = __commonJS({
|
|
|
6579
6638
|
logger2.info(`Starting Litd service (Tor: ${useTor})...`);
|
|
6580
6639
|
const litdArgs = buildLitdArgs(useTor);
|
|
6581
6640
|
await startService("litd", litdArgs);
|
|
6641
|
+
invalidateTerminalStatusCache();
|
|
6582
6642
|
logger2.info("Litd service started successfully");
|
|
6583
6643
|
}
|
|
6584
6644
|
const endStatus = await getTerminalStatus();
|
|
@@ -6600,6 +6660,8 @@ var require_nodeManage = __commonJS({
|
|
|
6600
6660
|
} catch (error) {
|
|
6601
6661
|
logger2.error(`Failed to start terminal services: ${error.message}`);
|
|
6602
6662
|
throw error;
|
|
6663
|
+
} finally {
|
|
6664
|
+
isStartingTerminal = false;
|
|
6603
6665
|
}
|
|
6604
6666
|
}
|
|
6605
6667
|
__name(startTerminal, "startTerminal");
|
|
@@ -6613,6 +6675,7 @@ var require_nodeManage = __commonJS({
|
|
|
6613
6675
|
logger2.info("Stopping terminal services...");
|
|
6614
6676
|
try {
|
|
6615
6677
|
const stopRet = await stopService("litd");
|
|
6678
|
+
invalidateTerminalStatusCache();
|
|
6616
6679
|
if (!stopRet) {
|
|
6617
6680
|
logger2.warn("stopService returned a falsy result");
|
|
6618
6681
|
return false;
|
|
@@ -6706,6 +6769,11 @@ var require_nodeManage = __commonJS({
|
|
|
6706
6769
|
async function startRGB(args = {}) {
|
|
6707
6770
|
const { waitForRunning = true, lnlinkUser } = args;
|
|
6708
6771
|
const logger2 = new Logger("rgbService");
|
|
6772
|
+
if (isStartingRGB) {
|
|
6773
|
+
logger2.warn("RGB start already in progress, returning current status");
|
|
6774
|
+
return await getRGBStatus();
|
|
6775
|
+
}
|
|
6776
|
+
isStartingRGB = true;
|
|
6709
6777
|
logger2.info("Starting RGB service...");
|
|
6710
6778
|
try {
|
|
6711
6779
|
const startStatus = await getRGBStatus();
|
|
@@ -6740,6 +6808,8 @@ var require_nodeManage = __commonJS({
|
|
|
6740
6808
|
} catch (error) {
|
|
6741
6809
|
logger2.error(`Failed to start RGB service: ${error.message}`);
|
|
6742
6810
|
throw error;
|
|
6811
|
+
} finally {
|
|
6812
|
+
isStartingRGB = false;
|
|
6743
6813
|
}
|
|
6744
6814
|
}
|
|
6745
6815
|
__name(startRGB, "startRGB");
|
|
@@ -6848,24 +6918,6 @@ var require_nodeManage = __commonJS({
|
|
|
6848
6918
|
}
|
|
6849
6919
|
}
|
|
6850
6920
|
__name(updateNodeName, "updateNodeName");
|
|
6851
|
-
if (globalThis.addCleanupFunction) {
|
|
6852
|
-
const logger2 = new Logger("nodeManage");
|
|
6853
|
-
globalThis.addCleanupFunction(async () => {
|
|
6854
|
-
logger2.info("Cleaning up node processes...");
|
|
6855
|
-
try {
|
|
6856
|
-
for (const name of ["litd", "tor", "rgb"]) {
|
|
6857
|
-
try {
|
|
6858
|
-
await stopService(name);
|
|
6859
|
-
logger2.info(`${name} process stopped`);
|
|
6860
|
-
} catch (err) {
|
|
6861
|
-
logger2.warn(`Failed to stop ${name}: ${err.message}`);
|
|
6862
|
-
}
|
|
6863
|
-
}
|
|
6864
|
-
} catch (error) {
|
|
6865
|
-
logger2.error(`Error during node cleanup: ${error.message}`);
|
|
6866
|
-
}
|
|
6867
|
-
});
|
|
6868
|
-
}
|
|
6869
6921
|
module2.exports = {
|
|
6870
6922
|
// Terminal (Litd + Tor) management
|
|
6871
6923
|
startTerminal,
|
|
@@ -7127,7 +7179,7 @@ var require_package = __commonJS({
|
|
|
7127
7179
|
"package.json"(exports2, module2) {
|
|
7128
7180
|
module2.exports = {
|
|
7129
7181
|
name: "lnlink-server",
|
|
7130
|
-
version: "1.1.
|
|
7182
|
+
version: "1.1.3",
|
|
7131
7183
|
private: false,
|
|
7132
7184
|
main: "dist/index.js",
|
|
7133
7185
|
files: [
|
|
@@ -7137,13 +7189,13 @@ var require_package = __commonJS({
|
|
|
7137
7189
|
],
|
|
7138
7190
|
scripts: {
|
|
7139
7191
|
build: "node build.js && node build.js --mode development --external all --entry electron",
|
|
7140
|
-
"start:bin": "
|
|
7192
|
+
"start:bin": "node scripts/start-bin.js",
|
|
7141
7193
|
"start:docker:dev": "dotenv -e .env.dev -- docker compose -f ./docker-compose.dev.yml up --build",
|
|
7142
7194
|
"start:dev": 'dotenv -e .env.dev -- sh -c "prisma generate && (prisma migrate dev --name auto_update || prisma db push) && clinic heapprof -- node ./app.js"',
|
|
7143
7195
|
"start:regtest": "docker compose --env-file ./.env.regtest -f ./docker-compose-lnlink.yml up --build",
|
|
7144
7196
|
"start:testnet": "docker compose --env-file ./.env.testnet -f ./docker-compose-lnlink.yml up --build",
|
|
7145
7197
|
"start:mainnet": "docker compose --env-file ./.env.mainnet -f ./docker-compose-lnlink.yml up --build",
|
|
7146
|
-
"start:bin:dist": "
|
|
7198
|
+
"start:bin:dist": "node scripts/start-bin.js --dist",
|
|
7147
7199
|
lint: "eslint .",
|
|
7148
7200
|
"lint:fix": "eslint . --fix",
|
|
7149
7201
|
"lint:staged": "lint-staged",
|
|
@@ -7462,13 +7514,9 @@ var require_lndService = __commonJS({
|
|
|
7462
7514
|
LINK_NODE_ADDR,
|
|
7463
7515
|
LINK_LND_PEER_LISTEN_PORT
|
|
7464
7516
|
} = getConfig2();
|
|
7465
|
-
const currentWalletState = await getWalletState(true);
|
|
7466
|
-
const terminalStatus = await getTerminalStatus();
|
|
7467
|
-
const linkStatusObj = {};
|
|
7468
|
-
terminalStatus.forEach((item) => {
|
|
7469
|
-
linkStatusObj[item.service_name] = item.status;
|
|
7470
|
-
});
|
|
7471
7517
|
const logger2 = new Logger("lnd");
|
|
7518
|
+
const version = packageJSON.version;
|
|
7519
|
+
const currentWalletState = await getWalletState(true);
|
|
7472
7520
|
const timeoutMs = 15e3;
|
|
7473
7521
|
const fallbackCombineInfo = linkCache.get("combineNodeInfo") || {};
|
|
7474
7522
|
let timeoutId;
|
|
@@ -7481,16 +7529,34 @@ var require_lndService = __commonJS({
|
|
|
7481
7529
|
});
|
|
7482
7530
|
}, timeoutMs);
|
|
7483
7531
|
});
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7532
|
+
let results;
|
|
7533
|
+
try {
|
|
7534
|
+
results = await Promise.allSettled([
|
|
7535
|
+
Promise.race([
|
|
7536
|
+
combineNodeInfoAsync(currentWalletState).then((data2) => ({ fromCache: false, data: data2 })),
|
|
7537
|
+
timeoutPromise
|
|
7538
|
+
]),
|
|
7539
|
+
getTerminalStatus(),
|
|
7540
|
+
checkTprEnabled(),
|
|
7541
|
+
getLnlinkUser({ account_type: ACCOUNT_TYPE.READ_ONLY })
|
|
7542
|
+
]);
|
|
7543
|
+
} finally {
|
|
7544
|
+
clearTimeout(timeoutId);
|
|
7545
|
+
}
|
|
7546
|
+
const [combineSettled, terminalSettled, tprSettled, userSettled] = results;
|
|
7547
|
+
const combineInfo = combineSettled.value?.data || {};
|
|
7548
|
+
const terminalStatus = terminalSettled.status === "fulfilled" ? terminalSettled.value : [];
|
|
7549
|
+
const taprootAssetsEnabled = tprSettled.status === "fulfilled" ? tprSettled.value : false;
|
|
7550
|
+
const readOnlyAccount = userSettled.status === "fulfilled" ? userSettled.value : null;
|
|
7551
|
+
if (terminalSettled.status === "rejected") {
|
|
7552
|
+
logger2.warn(`getNodeInfo: getTerminalStatus failed: ${terminalSettled.reason?.message}`);
|
|
7553
|
+
}
|
|
7554
|
+
if (userSettled.status === "rejected") {
|
|
7555
|
+
logger2.warn(`getNodeInfo: getLnlinkUser failed: ${userSettled.reason?.message}`);
|
|
7556
|
+
}
|
|
7557
|
+
const linkStatusObj = {};
|
|
7558
|
+
terminalStatus.forEach((item) => {
|
|
7559
|
+
linkStatusObj[item.service_name] = item.status;
|
|
7494
7560
|
});
|
|
7495
7561
|
const uri = combineInfo?.uris?.[0];
|
|
7496
7562
|
const data = {
|
|
@@ -7722,6 +7788,9 @@ var require_lndService = __commonJS({
|
|
|
7722
7788
|
async function combineNodeInfoAsync(walletState) {
|
|
7723
7789
|
let retInfo = {};
|
|
7724
7790
|
const logger2 = new Logger("lnd");
|
|
7791
|
+
const CACHE_KEY = "combineNodeInfo";
|
|
7792
|
+
const CACHE_TTL_KEY = "combineNodeInfo_ts";
|
|
7793
|
+
const CACHE_TTL_MS = 5e3;
|
|
7725
7794
|
try {
|
|
7726
7795
|
const { isMacaroonDecrypted } = getCacheMacaroon();
|
|
7727
7796
|
let state = walletState;
|
|
@@ -7730,18 +7799,33 @@ var require_lndService = __commonJS({
|
|
|
7730
7799
|
state = WALLET_STATE_CODE.LOCKED;
|
|
7731
7800
|
}
|
|
7732
7801
|
}
|
|
7802
|
+
const cachedInfo = linkCache.get(CACHE_KEY);
|
|
7803
|
+
const cacheTimestamp = linkCache.get(CACHE_TTL_KEY);
|
|
7804
|
+
if (cachedInfo && cacheTimestamp && cachedInfo.state === state) {
|
|
7805
|
+
const age = Date.now() - cacheTimestamp;
|
|
7806
|
+
if (age < CACHE_TTL_MS) {
|
|
7807
|
+
logger2.debug(`combineNodeInfoAsync: returning cached result (age: ${age}ms)`);
|
|
7808
|
+
return cachedInfo;
|
|
7809
|
+
}
|
|
7810
|
+
}
|
|
7733
7811
|
if (state >= WALLET_STATE_CODE.RPC_ACTIVE && isMacaroonDecrypted && state !== WALLET_STATE_CODE.WAITING_TO_START) {
|
|
7734
7812
|
const lightningService = getLightningService();
|
|
7735
|
-
const { settings } = await getMainLnlinkConfig();
|
|
7736
7813
|
const ret = await Promise.allSettled([
|
|
7814
|
+
getMainLnlinkConfig(),
|
|
7737
7815
|
lightningService.getInfo(),
|
|
7738
7816
|
lightningService.walletBalance(),
|
|
7739
7817
|
lightningService.listPeers({})
|
|
7740
7818
|
]);
|
|
7741
|
-
const [infoResult, balanceResult, peersResult] = ret;
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
|
|
7819
|
+
const [configResult, infoResult, balanceResult, peersResult] = ret;
|
|
7820
|
+
let settings = null;
|
|
7821
|
+
if (configResult.status === "fulfilled") {
|
|
7822
|
+
settings = configResult.value?.settings;
|
|
7823
|
+
} else {
|
|
7824
|
+
logger2.warn(`combineNodeInfoAsync: getMainLnlinkConfig failed: ${configResult.reason?.message}`);
|
|
7825
|
+
}
|
|
7826
|
+
const nodeInfo = infoResult.status === "fulfilled" ? infoResult.value : null;
|
|
7827
|
+
const balance = balanceResult.status === "fulfilled" ? balanceResult.value : null;
|
|
7828
|
+
const retListpeers = peersResult.status === "fulfilled" ? peersResult.value : null;
|
|
7745
7829
|
const peers = retListpeers?.peers || [];
|
|
7746
7830
|
const mapPeers = peers.map((peer) => {
|
|
7747
7831
|
const isLnfiPeer = peer.pub_key === settings?.officialLndPeer;
|
|
@@ -7771,7 +7855,8 @@ var require_lndService = __commonJS({
|
|
|
7771
7855
|
...retInfo,
|
|
7772
7856
|
state
|
|
7773
7857
|
};
|
|
7774
|
-
linkCache.set(
|
|
7858
|
+
linkCache.set(CACHE_KEY, retInfo);
|
|
7859
|
+
linkCache.set(CACHE_TTL_KEY, Date.now());
|
|
7775
7860
|
return retInfo;
|
|
7776
7861
|
} catch (e) {
|
|
7777
7862
|
logger2.warn(`LND lndService combineNodeInfoAsync peer combineNodeInfo warn--->${e.message}`);
|
|
@@ -8291,6 +8376,15 @@ var require_lndService = __commonJS({
|
|
|
8291
8376
|
}
|
|
8292
8377
|
logger2.info("Stopping litd before config reload (to free ports)...");
|
|
8293
8378
|
await stopTerminal({ lnlinkUser, waitForStopped: true });
|
|
8379
|
+
if (!enableTor && torRunning) {
|
|
8380
|
+
logger2.info("Stopping Tor service (was running standalone)...");
|
|
8381
|
+
try {
|
|
8382
|
+
await stopService("tor");
|
|
8383
|
+
logger2.info("Tor service stopped successfully");
|
|
8384
|
+
} catch (torError) {
|
|
8385
|
+
logger2.warn(`Failed to stop Tor service: ${torError.message}`);
|
|
8386
|
+
}
|
|
8387
|
+
}
|
|
8294
8388
|
logger2.info("Reloading config after services stopped...");
|
|
8295
8389
|
await reloadConfig();
|
|
8296
8390
|
logger2.info("Starting litd with new Tor configuration...");
|
|
@@ -11908,12 +12002,17 @@ var require_info = __commonJS({
|
|
|
11908
12002
|
LINK_RGB_LDK_PEER_LISTENING_PORT
|
|
11909
12003
|
} = getConfig2();
|
|
11910
12004
|
const logger2 = new Logger("rgb");
|
|
11911
|
-
|
|
11912
|
-
|
|
11913
|
-
|
|
11914
|
-
|
|
11915
|
-
|
|
12005
|
+
const [statusResult, readOnlyAccountResult] = await Promise.allSettled([
|
|
12006
|
+
getRGBStatus(),
|
|
12007
|
+
getLnlinkUser({ account_type: ACCOUNT_TYPE.READ_ONLY })
|
|
12008
|
+
]);
|
|
12009
|
+
let statusEntries = {};
|
|
12010
|
+
if (statusResult.status === "fulfilled") {
|
|
12011
|
+
statusEntries = statusResult.value;
|
|
12012
|
+
} else {
|
|
12013
|
+
logger2.warn(`getCombinedNodeInfo - getRGBStatus failed: ${statusResult.reason?.message}`);
|
|
11916
12014
|
}
|
|
12015
|
+
const readOnlyAccount = readOnlyAccountResult.status === "fulfilled" ? readOnlyAccountResult.value : null;
|
|
11917
12016
|
const serviceRunning = statusEntries.status === ServiceStatus.RUNNING;
|
|
11918
12017
|
let nodeInfo = null;
|
|
11919
12018
|
let balance = {
|
|
@@ -11945,7 +12044,8 @@ var require_info = __commonJS({
|
|
|
11945
12044
|
] = await Promise.allSettled([
|
|
11946
12045
|
rgbClient.node.getNodeInfo(),
|
|
11947
12046
|
rgbClient.onchain.getBtcBalance({
|
|
11948
|
-
skip_sync:
|
|
12047
|
+
skip_sync: true
|
|
12048
|
+
// Skip sync for faster response
|
|
11949
12049
|
}),
|
|
11950
12050
|
rgbClient.lightning.listPeers({})
|
|
11951
12051
|
]);
|
|
@@ -11964,14 +12064,11 @@ var require_info = __commonJS({
|
|
|
11964
12064
|
} else {
|
|
11965
12065
|
logger2.warn(`getCombinedNodeInfo - listPeers failed: ${peersResult.reason?.message || peersResult.reason}`);
|
|
11966
12066
|
}
|
|
11967
|
-
rgbClient.rgb.refreshTransfers({ skip_sync:
|
|
12067
|
+
rgbClient.rgb.refreshTransfers({ skip_sync: true }).catch((error) => {
|
|
11968
12068
|
logger2.warn(`getCombinedNodeInfo - refreshTransfers failed: ${error.message}`);
|
|
11969
12069
|
});
|
|
11970
12070
|
}
|
|
11971
12071
|
}
|
|
11972
|
-
const readOnlyAccount = await getLnlinkUser({
|
|
11973
|
-
account_type: ACCOUNT_TYPE.READ_ONLY
|
|
11974
|
-
});
|
|
11975
12072
|
const data = {
|
|
11976
12073
|
pubkey: nodeInfo?.pubkey ?? null,
|
|
11977
12074
|
host: `${LINK_RGB_HOST}:${LINK_RGB_LDK_PEER_LISTENING_PORT}`,
|
|
@@ -19001,17 +19098,6 @@ var require_job = __commonJS({
|
|
|
19001
19098
|
logger2.info("Job system graceful shutdown completed");
|
|
19002
19099
|
}
|
|
19003
19100
|
__name(gracefulShutdown, "gracefulShutdown");
|
|
19004
|
-
process.on("SIGINT", gracefulShutdown);
|
|
19005
|
-
process.on("SIGTERM", gracefulShutdown);
|
|
19006
|
-
process.on("uncaughtException", (error) => {
|
|
19007
|
-
const logger2 = new Logger("job_uncaught");
|
|
19008
|
-
logger2.error(`Uncaught exception: ${error.message}`);
|
|
19009
|
-
gracefulShutdown();
|
|
19010
|
-
});
|
|
19011
|
-
process.on("unhandledRejection", (reason, promise) => {
|
|
19012
|
-
const logger2 = new Logger("job_unhandled");
|
|
19013
|
-
logger2.error(`Unhandled rejection at: ${promise}, reason: ${reason}`);
|
|
19014
|
-
});
|
|
19015
19101
|
module2.exports = {
|
|
19016
19102
|
initJobSystem,
|
|
19017
19103
|
startJobSystem,
|
|
@@ -19511,20 +19597,25 @@ var LnLink = class extends EventEmitter {
|
|
|
19511
19597
|
*/
|
|
19512
19598
|
async stop() {
|
|
19513
19599
|
try {
|
|
19514
|
-
|
|
19515
|
-
|
|
19516
|
-
|
|
19600
|
+
const { stopService, setShuttingDown } = require_processManager();
|
|
19601
|
+
setShuttingDown(true);
|
|
19602
|
+
console.info("Stopping LN-Link (jobs + rgb + litd + tor)...");
|
|
19603
|
+
await Promise.allSettled([
|
|
19604
|
+
// Job system shutdown (cron tasks, state monitoring)
|
|
19605
|
+
(async () => {
|
|
19606
|
+
const { gracefulShutdown: shutdownJobs } = require_job();
|
|
19607
|
+
await shutdownJobs();
|
|
19608
|
+
})().catch((err) => console.warn(`Job system shutdown failed: ${err.message}`)),
|
|
19609
|
+
// Stop all child processes in parallel
|
|
19610
|
+
...["rgb", "litd", "tor"].map(async (name) => {
|
|
19517
19611
|
try {
|
|
19518
|
-
console.info(`Stopping ${name} process...`);
|
|
19519
19612
|
await stopService(name);
|
|
19520
|
-
console.info(`${name}
|
|
19613
|
+
console.info(`${name} stopped`);
|
|
19521
19614
|
} catch (err) {
|
|
19522
19615
|
console.warn(`Failed to stop ${name}: ${err.message}`);
|
|
19523
19616
|
}
|
|
19524
|
-
}
|
|
19525
|
-
|
|
19526
|
-
console.warn(`Child process cleanup failed: ${err.message}`);
|
|
19527
|
-
}
|
|
19617
|
+
})
|
|
19618
|
+
]);
|
|
19528
19619
|
if (this.server) {
|
|
19529
19620
|
await new Promise((resolve) => {
|
|
19530
19621
|
this.server.close(() => {
|
|
@@ -19564,6 +19655,14 @@ var LnLink = class extends EventEmitter {
|
|
|
19564
19655
|
port: this.isRunning ? this.options.httpPort : null
|
|
19565
19656
|
};
|
|
19566
19657
|
}
|
|
19658
|
+
/**
|
|
19659
|
+
* Get PIDs of all managed child processes (litd, tor, rgb)
|
|
19660
|
+
* @returns {{ litd: number|null, tor: number|null, rgb: number|null }}
|
|
19661
|
+
*/
|
|
19662
|
+
getServicePids() {
|
|
19663
|
+
const { getServicePids } = require_processManager();
|
|
19664
|
+
return getServicePids();
|
|
19665
|
+
}
|
|
19567
19666
|
/**
|
|
19568
19667
|
* Get configuration
|
|
19569
19668
|
*/
|