mirror of
https://github.com/Ride-The-Lightning/RTL.git
synced 2026-08-13 12:33:07 +02:00
Fix for Resource temporarily unavailable error for CLN channel alias list
Fixes #1501
This commit is contained in:
parent
aae46f6443
commit
1cec7b125b
11 changed files with 119 additions and 24 deletions
|
|
@ -14,11 +14,12 @@ export const listPeerChannels = (req, res, next) => {
|
||||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeerchannels';
|
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeerchannels';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body.channels });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body.channels });
|
||||||
return Promise.all(body.channels?.map((channel) => {
|
const getPeerAliasesTasks = body.channels.map((channel) => () => {
|
||||||
channel.to_them_msat = channel.total_msat - channel.to_us_msat;
|
channel.to_them_msat = channel.total_msat - channel.to_us_msat;
|
||||||
channel.balancedness = (channel.total_msat === 0) ? 1 : (1 - Math.abs((channel.to_us_msat - (channel.total_msat - channel.to_us_msat)) / channel.total_msat)).toFixed(3);
|
channel.balancedness = (channel.total_msat === 0) ? 1 : (1 - Math.abs((channel.to_us_msat - channel.to_them_msat) / channel.total_msat)).toFixed(3);
|
||||||
return getAlias(req.session.selectedNode, channel, 'peer_id');
|
return getAlias(req.session.selectedNode, channel, 'peer_id');
|
||||||
})).then((values) => {
|
});
|
||||||
|
common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List With Aliases Received', data: body.channels });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List With Aliases Received', data: body.channels });
|
||||||
return res.status(200).json(body.channels || []);
|
return res.status(200).json(body.channels || []);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { Common } from '../../utils/common.js';
|
||||||
let options = null;
|
let options = null;
|
||||||
const logger = Logger;
|
const logger = Logger;
|
||||||
const common = Common;
|
const common = Common;
|
||||||
|
const aliasCache = new Map();
|
||||||
export const getRoute = (req, res, next) => {
|
export const getRoute = (req, res, next) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Routes..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Routes..' });
|
||||||
options = common.getOptions(req);
|
options = common.getOptions(req);
|
||||||
|
|
@ -80,20 +81,28 @@ export const listNodes = (req, res, next) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
export const getAlias = (selNode, peer, id) => {
|
export const getAlias = (selNode, peer, id) => {
|
||||||
options.url = selNode.settings.lnServerUrl + '/v1/listnodes';
|
const peerId = peer[id];
|
||||||
if (!peer[id]) {
|
if (!peerId) {
|
||||||
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
||||||
peer.alias = '';
|
peer.alias = '';
|
||||||
return peer;
|
return Promise.resolve(peer);
|
||||||
}
|
}
|
||||||
options.body = { id: peer[id] };
|
if (aliasCache.has(peerId)) {
|
||||||
|
peer.alias = aliasCache.get(peerId);
|
||||||
|
return Promise.resolve(peer);
|
||||||
|
}
|
||||||
|
options.url = selNode.settings.lnServerUrl + '/v1/listnodes';
|
||||||
|
options.body = { id: peerId };
|
||||||
return request.post(options).then((body) => {
|
return request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Network', msg: 'Peer Alias Finished', data: body });
|
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Network', msg: 'Peer Alias Finished', data: body });
|
||||||
peer.alias = body.nodes[0] && body.nodes[0].alias ? body.nodes[0].alias : peer[id].substring(0, 20);
|
const alias = body.nodes?.[0]?.alias || peerId.substring(0, 20);
|
||||||
|
aliasCache.set(peerId, alias);
|
||||||
|
peer.alias = alias;
|
||||||
return peer;
|
return peer;
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
common.handleError(errRes, 'Network', 'Peer Alias Error', selNode);
|
common.handleError(errRes, 'Network', 'Peer Alias Error', selNode);
|
||||||
peer.alias = peer[id].substring(0, 20);
|
const alias = peerId.substring(0, 20);
|
||||||
|
peer.alias = alias;
|
||||||
return peer;
|
return peer;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -608,6 +608,39 @@ export class CommonService {
|
||||||
const dataStr = foundDataLine ? foundDataLine.substring((foundDataLine.indexOf(search_string)) + search_string.length) : '{}';
|
const dataStr = foundDataLine ? foundDataLine.substring((foundDataLine.indexOf(search_string)) + search_string.length) : '{}';
|
||||||
return JSON.parse(dataStr);
|
return JSON.parse(dataStr);
|
||||||
};
|
};
|
||||||
|
this.runWithConcurrencyLimit = (tasks, limit, done) => {
|
||||||
|
const results = new Array(tasks.length);
|
||||||
|
let nextIndex = 0;
|
||||||
|
let activeCount = 0;
|
||||||
|
const runNext = () => {
|
||||||
|
if (nextIndex >= tasks.length) {
|
||||||
|
if (activeCount === 0) {
|
||||||
|
done(results); // all tasks are finished
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const currentIndex = nextIndex++;
|
||||||
|
activeCount++;
|
||||||
|
const task = tasks[currentIndex];
|
||||||
|
if (typeof task !== 'function') {
|
||||||
|
results[currentIndex] = { error: new Error('Invalid task at index ' + currentIndex) };
|
||||||
|
activeCount--;
|
||||||
|
runNext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Promise.resolve().then(() => task()).then((result) => {
|
||||||
|
results[currentIndex] = result;
|
||||||
|
}).catch((err) => {
|
||||||
|
results[currentIndex] = { error: err };
|
||||||
|
}).finally(() => {
|
||||||
|
activeCount--;
|
||||||
|
runNext();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
for (let i = 0; i < limit && i < tasks.length; i++) {
|
||||||
|
runNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const Common = new CommonService();
|
export const Common = new CommonService();
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
frontend/styles.0fe91e37be16ca28.css
Normal file
1
frontend/styles.0fe91e37be16ca28.css
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -14,11 +14,12 @@ export const listPeerChannels = (req, res, next) => {
|
||||||
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeerchannels';
|
options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/listpeerchannels';
|
||||||
request.post(options).then((body) => {
|
request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body.channels });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List Received', data: body.channels });
|
||||||
return Promise.all(body.channels?.map((channel) => {
|
const getPeerAliasesTasks = body.channels.map((channel) => () => {
|
||||||
channel.to_them_msat = channel.total_msat - channel.to_us_msat;
|
channel.to_them_msat = channel.total_msat - channel.to_us_msat;
|
||||||
channel.balancedness = (channel.total_msat === 0) ? 1 : (1 - Math.abs((channel.to_us_msat - (channel.total_msat - channel.to_us_msat)) / channel.total_msat)).toFixed(3);
|
channel.balancedness = (channel.total_msat === 0) ? 1 : (1 - Math.abs((channel.to_us_msat - channel.to_them_msat) / channel.total_msat)).toFixed(3);
|
||||||
return getAlias(req.session.selectedNode, channel, 'peer_id');
|
return getAlias(req.session.selectedNode, channel, 'peer_id');
|
||||||
})).then((values) => {
|
});
|
||||||
|
common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List With Aliases Received', data: body.channels });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Channels', msg: 'Peer Channels List With Aliases Received', data: body.channels });
|
||||||
return res.status(200).json(body.channels || []);
|
return res.status(200).json(body.channels || []);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { SelectedNode } from '../../models/config.model.js';
|
||||||
let options = null;
|
let options = null;
|
||||||
const logger: LoggerService = Logger;
|
const logger: LoggerService = Logger;
|
||||||
const common: CommonService = Common;
|
const common: CommonService = Common;
|
||||||
|
const aliasCache = new Map<string, string>();
|
||||||
|
|
||||||
export const getRoute = (req, res, next) => {
|
export const getRoute = (req, res, next) => {
|
||||||
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Routes..' });
|
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'Network', msg: 'Getting Network Routes..' });
|
||||||
|
|
@ -79,20 +80,31 @@ export const listNodes = (req, res, next) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getAlias = (selNode: SelectedNode, peer: any, id: string) => {
|
export const getAlias = (selNode: SelectedNode, peer: any, id: string) => {
|
||||||
options.url = selNode.settings.lnServerUrl + '/v1/listnodes';
|
const peerId = peer[id];
|
||||||
if (!peer[id]) {
|
if (!peerId) {
|
||||||
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
logger.log({ selectedNode: selNode, level: 'ERROR', fileName: 'Network', msg: 'Empty Peer ID' });
|
||||||
peer.alias = '';
|
peer.alias = '';
|
||||||
return peer;
|
return Promise.resolve(peer);
|
||||||
}
|
}
|
||||||
options.body = { id : peer[id] };
|
|
||||||
|
if (aliasCache.has(peerId)) {
|
||||||
|
peer.alias = aliasCache.get(peerId)!;
|
||||||
|
return Promise.resolve(peer);
|
||||||
|
}
|
||||||
|
|
||||||
|
options.url = selNode.settings.lnServerUrl + '/v1/listnodes';
|
||||||
|
options.body = { id: peerId };
|
||||||
|
|
||||||
return request.post(options).then((body) => {
|
return request.post(options).then((body) => {
|
||||||
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Network', msg: 'Peer Alias Finished', data: body });
|
logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Network', msg: 'Peer Alias Finished', data: body });
|
||||||
peer.alias = body.nodes[0] && body.nodes[0].alias ? body.nodes[0].alias : peer[id].substring(0, 20);
|
const alias = body.nodes?.[0]?.alias || peerId.substring(0, 20);
|
||||||
|
aliasCache.set(peerId, alias);
|
||||||
|
peer.alias = alias;
|
||||||
return peer;
|
return peer;
|
||||||
}).catch((errRes) => {
|
}).catch((errRes) => {
|
||||||
common.handleError(errRes, 'Network', 'Peer Alias Error', selNode);
|
common.handleError(errRes, 'Network', 'Peer Alias Error', selNode);
|
||||||
peer.alias = peer[id].substring(0, 20);
|
const alias = peerId.substring(0, 20);
|
||||||
|
peer.alias = alias;
|
||||||
return peer;
|
return peer;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -581,6 +581,45 @@ export class CommonService {
|
||||||
return JSON.parse(dataStr);
|
return JSON.parse(dataStr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public runWithConcurrencyLimit = (tasks, limit, done) => {
|
||||||
|
const results = new Array(tasks.length);
|
||||||
|
let nextIndex = 0;
|
||||||
|
let activeCount = 0;
|
||||||
|
|
||||||
|
const runNext = () => {
|
||||||
|
if (nextIndex >= tasks.length) {
|
||||||
|
if (activeCount === 0) {
|
||||||
|
done(results); // all tasks are finished
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentIndex = nextIndex++;
|
||||||
|
activeCount++;
|
||||||
|
|
||||||
|
const task = tasks[currentIndex];
|
||||||
|
if (typeof task !== 'function') {
|
||||||
|
results[currentIndex] = { error: new Error('Invalid task at index ' + currentIndex) };
|
||||||
|
activeCount--;
|
||||||
|
runNext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.resolve().then(() => task()).then((result) => {
|
||||||
|
results[currentIndex] = result;
|
||||||
|
}).catch((err) => {
|
||||||
|
results[currentIndex] = { error: err };
|
||||||
|
}).finally(() => {
|
||||||
|
activeCount--;
|
||||||
|
runNext();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let i = 0; i < limit && i < tasks.length; i++) {
|
||||||
|
runNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Common = new CommonService();
|
export const Common = new CommonService();
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,6 @@
|
||||||
.tab-badge {
|
.tab-badge {
|
||||||
& .mat-badge-content {
|
& .mat-badge-content {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
padding-bottom: 2px;
|
|
||||||
&.mat-badge-active {
|
&.mat-badge-active {
|
||||||
background: $primary-color;
|
background: $primary-color;
|
||||||
}
|
}
|
||||||
|
|
@ -313,8 +312,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-badge-medium.mat-badge-after .mat-badge-content {
|
.mat-badge-medium.mat-badge-after .mat-badge-content {
|
||||||
right: unset;
|
|
||||||
margin-left: $gap !important;
|
margin-left: $gap !important;
|
||||||
|
width: fit-content;
|
||||||
|
padding: 0 $gap;
|
||||||
@include for_screensize(phone) {
|
@include for_screensize(phone) {
|
||||||
margin-left: 0 !important;
|
margin-left: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue