From cfa2e11171b87f33df91dc73c37e20ceb0893a9d Mon Sep 17 00:00:00 2001 From: Osuji Date: Tue, 4 Aug 2026 08:38:01 +0100 Subject: [PATCH] Fix options race in peers.ts alias resolution fan-outs --- backend/controllers/lnd/peers.js | 14 +++++++++----- server/controllers/lnd/peers.ts | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/backend/controllers/lnd/peers.js b/backend/controllers/lnd/peers.js index 917e910c..4fff74cc 100644 --- a/backend/controllers/lnd/peers.js +++ b/backend/controllers/lnd/peers.js @@ -4,9 +4,9 @@ import { Common } from '../../utils/common.js'; let options = null; const logger = Logger; const common = Common; -export const getAliasForPeers = (selNode, peer) => { - options.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + peer.pub_key; - return request(options).then((aliasBody) => { +export const getAliasForPeers = (selNode, peer, requestOptions) => { + requestOptions.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + peer.pub_key; + return request(requestOptions).then((aliasBody) => { logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Peers', msg: 'Alias Received', data: aliasBody.node.alias }); peer.alias = aliasBody.node.alias; return aliasBody.node.alias; @@ -22,12 +22,14 @@ export const getPeers = (req, res, next) => { return res.status(options.statusCode).json({ message: options.message, error: options.error }); } options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers'; + const selNode = req.session.selectedNode; + const { qs: _qs, ...requestOptions } = options; request(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body }); const peers = !body.peers ? [] : body.peers; // Bound concurrent alias lookups so a node with many peers can't fire one graph/node // request per peer at once and overwhelm the backend (parity with the CLN fix, #1501). - const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(req.session.selectedNode, peer)); + const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(selNode, peer, { ...requestOptions })); common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => { // Guard the response-send: the limiter invokes this outside the surrounding .catch. try { @@ -58,13 +60,15 @@ export const postPeer = (req, res, next) => { addr: { host: host, pubkey: pubkey }, perm: perm }); + const selNode = req.session.selectedNode; + const { qs: _qs, ...requestOptions } = options; request.post(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peer Connected', data: body }); options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers'; request(options).then((body) => { const peers = (!body.peers) ? [] : body.peers; // Bound concurrent alias lookups (parity with the CLN fix, #1501). - const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(req.session.selectedNode, peer)); + const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(selNode, peer, { ...requestOptions })); common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => { // Guard the response-send: the limiter invokes this outside the surrounding .catch, and // this replaced an explicit inner .catch — a throw here must not hang the POST (#1629 F4). diff --git a/server/controllers/lnd/peers.ts b/server/controllers/lnd/peers.ts index 3f460b65..03fc3838 100644 --- a/server/controllers/lnd/peers.ts +++ b/server/controllers/lnd/peers.ts @@ -6,9 +6,9 @@ let options = null; const logger: LoggerService = Logger; const common: CommonService = Common; -export const getAliasForPeers = (selNode: SelectedNode, peer) => { - options.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + peer.pub_key; - return request(options).then((aliasBody) => { +export const getAliasForPeers = (selNode: SelectedNode, peer, requestOptions) => { + requestOptions.url = selNode.settings.lnServerUrl + '/v1/graph/node/' + peer.pub_key; + return request(requestOptions).then((aliasBody) => { logger.log({ selectedNode: selNode, level: 'DEBUG', fileName: 'Peers', msg: 'Alias Received', data: aliasBody.node.alias }); peer.alias = aliasBody.node.alias; return aliasBody.node.alias; @@ -23,12 +23,14 @@ export const getPeers = (req, res, next) => { options = common.getOptions(req); if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); } options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers'; + const selNode = req.session.selectedNode; + const { qs: _qs, ...requestOptions } = options; request(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peers List Received', data: body }); const peers = !body.peers ? [] : body.peers; // Bound concurrent alias lookups so a node with many peers can't fire one graph/node // request per peer at once and overwhelm the backend (parity with the CLN fix, #1501). - const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(req.session.selectedNode, peer)); + const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(selNode, peer, { ...requestOptions })); common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => { // Guard the response-send: the limiter invokes this outside the surrounding .catch. try { @@ -55,13 +57,15 @@ export const postPeer = (req, res, next) => { addr: { host: host, pubkey: pubkey }, perm: perm }); + const selNode = req.session.selectedNode; + const { qs: _qs, ...requestOptions } = options; request.post(options).then((body) => { logger.log({ selectedNode: req.session.selectedNode, level: 'DEBUG', fileName: 'Peers', msg: 'Peer Connected', data: body }); options.url = req.session.selectedNode.settings.lnServerUrl + '/v1/peers'; request(options).then((body) => { const peers = (!body.peers) ? [] : body.peers; // Bound concurrent alias lookups (parity with the CLN fix, #1501). - const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(req.session.selectedNode, peer)); + const getPeerAliasesTasks = peers.map((peer) => () => getAliasForPeers(selNode, peer, { ...requestOptions })); common.runWithConcurrencyLimit(getPeerAliasesTasks, 20, () => { // Guard the response-send: the limiter invokes this outside the surrounding .catch, and // this replaced an explicit inner .catch — a throw here must not hang the POST (#1629 F4).