grpc-libp2p-client 0.0.37 → 0.0.38

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/index.cjs.js CHANGED
@@ -357,7 +357,7 @@ class HPACK {
357
357
  }
358
358
  // Huffman编码实现
359
359
  huffmanEncode(bytes) {
360
- let result = [];
360
+ const result = [];
361
361
  let current = 0;
362
362
  let bits = 0;
363
363
  for (let i = 0; i < bytes.length; i++) {
@@ -450,7 +450,7 @@ class HPACK {
450
450
  try {
451
451
  result = this.decode(bytes);
452
452
  }
453
- catch (e) {
453
+ catch {
454
454
  result = '';
455
455
  }
456
456
  }
@@ -458,7 +458,7 @@ class HPACK {
458
458
  try {
459
459
  result = new TextDecoder().decode(bytes);
460
460
  }
461
- catch (e) {
461
+ catch {
462
462
  result = '';
463
463
  }
464
464
  }
@@ -504,7 +504,8 @@ class FrameEncoder {
504
504
  // 编码SETTINGS帧
505
505
  static encodeSettingsFrame(frame) {
506
506
  // 计算payload总长度:每个设置项占6字节
507
- const payloadLength = frame.payload.length * 6;
507
+ const settingsPayload = frame.payload;
508
+ const payloadLength = settingsPayload.length * 6;
508
509
  // 分配缓冲区:9字节头部 + payload长度
509
510
  const buffer = new Uint8Array(9 + payloadLength);
510
511
  // 编码帧头部(前9个字节)
@@ -515,7 +516,7 @@ class FrameEncoder {
515
516
  streamId: frame.streamId
516
517
  });
517
518
  // 编码payload
518
- _encodeSettingsPayload(buffer, frame.payload);
519
+ _encodeSettingsPayload(buffer, settingsPayload);
519
520
  return buffer;
520
521
  }
521
522
  // 编码SETTINGS ACK帧
@@ -585,11 +586,11 @@ const defaultSettings = {
585
586
  [SETTINGS_PARAMETERS.MAX_FRAME_SIZE]: 16 << 10, // 16k
586
587
  [SETTINGS_PARAMETERS.MAX_HEADER_LIST_SIZE]: 8192
587
588
  };
588
- const HTTP2_PREFACE = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n';
589
+ const HTTP2_PREFACE$1 = 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n';
589
590
  class Http2Frame {
590
591
  // 创建并编码PREFACE帧
591
592
  static createPreface() {
592
- return new TextEncoder().encode(HTTP2_PREFACE);
593
+ return new TextEncoder().encode(HTTP2_PREFACE$1);
593
594
  }
594
595
  static createPongFrame(payload) {
595
596
  return Http2Frame.createFrame(0x6, 0x1, 0, payload);
@@ -806,6 +807,7 @@ function _createPayload(settings) {
806
807
  return payload;
807
808
  }
808
809
 
810
+ const HTTP2_PREFACE = new TextEncoder().encode("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
809
811
  class HTTP2Parser {
810
812
  constructor(writer, options) {
811
813
  this.buffer = new Uint8Array(0);
@@ -853,44 +855,49 @@ class HTTP2Parser {
853
855
  // 处理单个数据块
854
856
  _processChunk(chunk) {
855
857
  // chunk 是 Uint8ArrayList 或 Uint8Array
856
- const newData = chunk.subarray ? chunk.subarray() : new Uint8Array(chunk);
857
- // 累积数据到buffer
858
+ const newData = 'subarray' in chunk && typeof chunk.subarray === 'function'
859
+ ? chunk.subarray()
860
+ : chunk;
861
+ // 原作者之前的 O(N) 内存拷贝优化被保留,去掉了存在 onEnd 竞态的 setTimeout
858
862
  const newBuffer = new Uint8Array(this.buffer.length + newData.length);
859
863
  newBuffer.set(this.buffer);
860
864
  newBuffer.set(newData, this.buffer.length);
861
865
  this.buffer = newBuffer;
862
866
  // 持续处理所有完整的帧
863
- while (this.buffer.length >= 9) {
867
+ let readOffset = 0;
868
+ while (this.buffer.length - readOffset >= 9) {
864
869
  // 判断是否有HTTP/2前导
865
- if (this.buffer.length >= 24 && this.isHttp2Preface(this.buffer)) {
866
- this.buffer = this.buffer.slice(24);
870
+ if (this.buffer.length - readOffset >= 24 && this.isHttp2Preface(this.buffer.subarray(readOffset))) {
871
+ readOffset += 24;
867
872
  // 发送SETTINGS帧
868
873
  const settingFrame = Http2Frame.createSettingsFrame();
869
874
  this.writer.write(settingFrame);
870
- break;
875
+ continue;
871
876
  }
872
- const frameHeader = this._parseFrameHeader(this.buffer);
877
+ const frameHeader = this._parseFrameHeader(this.buffer.subarray(readOffset));
873
878
  const totalFrameLength = 9 + frameHeader.length;
874
879
  // 检查是否有完整的帧
875
- if (this.buffer.length < totalFrameLength) {
880
+ if (this.buffer.length - readOffset < totalFrameLength) {
876
881
  break;
877
882
  }
878
883
  // 获取完整帧数据
879
- const frameData = this.buffer.slice(0, totalFrameLength);
884
+ const frameData = this.buffer.subarray(readOffset, readOffset + totalFrameLength);
880
885
  // 处理不同类型的帧
881
886
  this._handleFrame(frameHeader, frameData).catch((err) => {
882
887
  console.error("Error handling frame:", err);
883
888
  });
884
- // 移除已处理的帧
885
- this.buffer = this.buffer.slice(totalFrameLength);
889
+ // 移动偏移量
890
+ readOffset += totalFrameLength;
891
+ }
892
+ if (readOffset > 0) {
893
+ this.buffer = this.buffer.slice(readOffset);
886
894
  }
887
895
  }
888
896
  isHttp2Preface(buffer) {
889
- const PREFACE = new TextEncoder().encode("PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n");
890
- if (buffer.length < PREFACE.length)
897
+ if (buffer.length < HTTP2_PREFACE.length)
891
898
  return false;
892
- for (let i = 0; i < PREFACE.length; i++) {
893
- if (buffer[i] !== PREFACE[i])
899
+ for (let i = 0; i < HTTP2_PREFACE.length; i++) {
900
+ if (buffer[i] !== HTTP2_PREFACE[i])
894
901
  return false;
895
902
  }
896
903
  return true;
@@ -1077,7 +1084,9 @@ class HTTP2Parser {
1077
1084
  waiters.forEach(fn => { try {
1078
1085
  fn();
1079
1086
  }
1080
- catch { } });
1087
+ catch (e) {
1088
+ console.debug('waiter error', e);
1089
+ } });
1081
1090
  }
1082
1091
  break;
1083
1092
  case FRAME_TYPES.DATA:
@@ -1126,7 +1135,7 @@ class HTTP2Parser {
1126
1135
  break;
1127
1136
  case FRAME_TYPES.WINDOW_UPDATE:
1128
1137
  // 处理窗口更新帧
1129
- this.handleWindowUpdateFrame(frameHeader, frameData, frameHeader.streamId);
1138
+ this.handleWindowUpdateFrame(frameHeader, frameData);
1130
1139
  // 更新发送窗口(对端接收窗口)
1131
1140
  try {
1132
1141
  const inc = this.parseWindowUpdateFrame(frameData, frameHeader).windowSizeIncrement;
@@ -1141,9 +1150,11 @@ class HTTP2Parser {
1141
1150
  waiters.forEach(fn => { try {
1142
1151
  fn();
1143
1152
  }
1144
- catch { } });
1153
+ catch (e) {
1154
+ console.debug('waiter error', e);
1155
+ } });
1145
1156
  }
1146
- catch (e) { }
1157
+ catch { /* ignore WINDOW_UPDATE parse errors */ }
1147
1158
  break;
1148
1159
  case FRAME_TYPES.PING:
1149
1160
  // 处理PING帧
@@ -1165,7 +1176,7 @@ class HTTP2Parser {
1165
1176
  info = {};
1166
1177
  }
1167
1178
  }
1168
- catch { }
1179
+ catch { /* ignore GOAWAY parse errors */ }
1169
1180
  try {
1170
1181
  this.onGoaway?.(info ?? {});
1171
1182
  }
@@ -1298,7 +1309,7 @@ class HTTP2Parser {
1298
1309
  };
1299
1310
  }
1300
1311
  // 处理 WINDOW_UPDATE 帧
1301
- handleWindowUpdateFrame(frameHeader, payload, streamId) {
1312
+ handleWindowUpdateFrame(frameHeader, payload) {
1302
1313
  try {
1303
1314
  const windowUpdate = this.parseWindowUpdateFrame(payload, frameHeader);
1304
1315
  this.connectionWindowSize += windowUpdate.windowSizeIncrement;
@@ -1439,8 +1450,8 @@ class StreamWriter {
1439
1450
  }
1440
1451
  catch (err) {
1441
1452
  // Gracefully handle stream closing errors - 不要传递到 handleError
1442
- const errMsg = err.message?.toLowerCase() || '';
1443
- if (err.name === 'StreamStateError' ||
1453
+ const errMsg = (err instanceof Error ? err.message : '').toLowerCase();
1454
+ if ((err instanceof Error && err.name === 'StreamStateError') ||
1444
1455
  errMsg.includes('closing') ||
1445
1456
  errMsg.includes('closed') ||
1446
1457
  errMsg.includes('write to a stream that is closed')) {
@@ -1452,6 +1463,7 @@ class StreamWriter {
1452
1463
  }
1453
1464
  }
1454
1465
  createTransform() {
1466
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
1455
1467
  const self = this;
1456
1468
  return async function* (source) {
1457
1469
  for await (const chunk of source) {
@@ -1461,7 +1473,7 @@ class StreamWriter {
1461
1473
  // 因此这里统计的 bytesDrained 更接近实际被 sink 消费的字节数
1462
1474
  try {
1463
1475
  // 在下游消费后再扣减待消费队列,避免误判“next 没取”
1464
- if (self.p?._queueSize != null) {
1476
+ if (self.p._queueSize != null) {
1465
1477
  self.p._queueSize = Math.max(0, self.p._queueSize - chunk.byteLength);
1466
1478
  }
1467
1479
  self.bytesDrained += chunk.byteLength;
@@ -1542,6 +1554,8 @@ class StreamWriter {
1542
1554
  return data.arrayBuffer();
1543
1555
  if (typeof data === 'string')
1544
1556
  return new TextEncoder().encode(data).buffer;
1557
+ if (data instanceof Uint8Array)
1558
+ return data.buffer.slice(data.byteOffset, data.byteOffset + data.byteLength);
1545
1559
  return data;
1546
1560
  }
1547
1561
  async writeChunks(buffer) {
@@ -1684,7 +1698,7 @@ class StreamWriter {
1684
1698
  }
1685
1699
  catch (err) {
1686
1700
  // 忽略关闭已关闭流的错误
1687
- const errMsg = err.message?.toLowerCase() || '';
1701
+ const errMsg = (err instanceof Error ? err.message : '').toLowerCase();
1688
1702
  if (!errMsg.includes('closed') && !errMsg.includes('closing')) {
1689
1703
  this.log?.trace?.('Stream close error:', err);
1690
1704
  }
@@ -1702,7 +1716,8 @@ class StreamWriter {
1702
1716
  // 先检查流状态,避免在已关闭的流上调用 abort
1703
1717
  if (this.stream && typeof this.stream.abort === 'function') {
1704
1718
  // 检查流的状态,避免操作已关闭的流
1705
- const streamState = this.stream.status || this.stream.state;
1719
+ const streamState = this.stream.status ||
1720
+ this.stream.state;
1706
1721
  if (streamState !== 'closed' && streamState !== 'closing') {
1707
1722
  this.stream.abort(new Error(reason));
1708
1723
  }
@@ -1711,7 +1726,7 @@ class StreamWriter {
1711
1726
  catch (err) {
1712
1727
  // Stream may already be closed, ignore all stream-related errors
1713
1728
  // 完全忽略流操作错误,避免在错误处理中再次抛出错误
1714
- const errMsg = err.message?.toLowerCase() || '';
1729
+ const errMsg = (err instanceof Error ? err.message : '').toLowerCase();
1715
1730
  if (!errMsg.includes('closed') && !errMsg.includes('closing') && !errMsg.includes('write')) {
1716
1731
  this.log?.trace?.('Stream abort error:', err);
1717
1732
  }
@@ -1733,13 +1748,13 @@ class StreamWriter {
1733
1748
  }
1734
1749
  // 立即拒绝所有待处理的写入任务,避免它们继续执行
1735
1750
  const pendingTasks = this.writeQueue.splice(0);
1736
- pendingTasks.forEach(task => {
1751
+ pendingTasks.forEach(() => {
1737
1752
  // 这些任务的 Promise 会在执行时因为检查到 aborted 而被拒绝
1738
1753
  });
1739
1754
  try {
1740
1755
  this.p.end();
1741
1756
  }
1742
- catch (err) {
1757
+ catch {
1743
1758
  // Ignore errors when ending pushable
1744
1759
  }
1745
1760
  if (this.watchdogTimer) {
@@ -1879,6 +1894,7 @@ class Libp2pGrpcClient {
1879
1894
  }
1880
1895
  await new Promise((resolve, reject) => {
1881
1896
  let settled = false;
1897
+ // eslint-disable-next-line prefer-const
1882
1898
  let timeoutId;
1883
1899
  const cleanup = () => {
1884
1900
  const idx = state.waiters.indexOf(waiter);
@@ -1961,7 +1977,7 @@ class Libp2pGrpcClient {
1961
1977
  if (pooled) {
1962
1978
  const conn = pooled.connection;
1963
1979
  if (conn) {
1964
- const status = conn?.stat?.status?.toLowerCase?.();
1980
+ const status = conn.status;
1965
1981
  if (!status || status === "open") {
1966
1982
  return conn;
1967
1983
  }
@@ -1988,17 +2004,9 @@ class Libp2pGrpcClient {
1988
2004
  }
1989
2005
  };
1990
2006
  try {
1991
- const anyConn = conn;
1992
- if (typeof anyConn.addEventListener === "function") {
1993
- anyConn.addEventListener("close", removeFromPool, {
1994
- once: true,
1995
- });
1996
- }
1997
- else if (typeof anyConn.once === "function") {
1998
- anyConn.once("close", removeFromPool);
1999
- }
2007
+ conn.addEventListener("close", removeFromPool, { once: true });
2000
2008
  }
2001
- catch { }
2009
+ catch { /* ignore event listener registration errors */ }
2002
2010
  }
2003
2011
  }
2004
2012
  return conn;
@@ -2068,14 +2076,14 @@ class Libp2pGrpcClient {
2068
2076
  });
2069
2077
  try {
2070
2078
  writer.addEventListener("backpressure", (e) => {
2071
- const d = e?.detail || {};
2079
+ const d = e.detail || {};
2072
2080
  console.warn(`[unary stream ${streamId}] backpressure current=${d.currentSize} avg=${d.averageSize} threshold=${d.threshold}`);
2073
2081
  });
2074
- writer.addEventListener("drain", (e) => {
2075
- const d = e?.detail || {};
2082
+ writer.addEventListener("drain", () => {
2083
+ // drain event - no action needed
2076
2084
  });
2077
2085
  writer.addEventListener("stalled", (e) => {
2078
- const d = e?.detail || {};
2086
+ const d = e.detail || {};
2079
2087
  console.warn(`[unary stream ${streamId}] stalled queue=${d.queueSize} drained=${d.drained} since=${d.sinceMs}ms — sending PING`);
2080
2088
  try {
2081
2089
  const payload = new Uint8Array(8);
@@ -2083,10 +2091,10 @@ class Libp2pGrpcClient {
2083
2091
  const ping = Http2Frame.createFrame(0x6, 0x0, 0, payload);
2084
2092
  writer.write(ping);
2085
2093
  }
2086
- catch { }
2094
+ catch { /* ignore ping write errors */ }
2087
2095
  });
2088
2096
  }
2089
- catch { }
2097
+ catch { /* ignore addEventListener errors */ }
2090
2098
  const parser = new HTTP2Parser(writer);
2091
2099
  parser.onGoaway = (info) => {
2092
2100
  console.warn("[unaryCall] GOAWAY received from server", info);
@@ -2097,7 +2105,7 @@ class Libp2pGrpcClient {
2097
2105
  exitFlag = true;
2098
2106
  errMsg = `GOAWAY received: code=${info.errorCode}`;
2099
2107
  try {
2100
- connection?.close?.();
2108
+ connection?.close();
2101
2109
  }
2102
2110
  catch (err) {
2103
2111
  console.warn("Error closing connection after GOAWAY:", err);
@@ -2122,7 +2130,6 @@ class Libp2pGrpcClient {
2122
2130
  if (payload.length < 5) {
2123
2131
  return;
2124
2132
  }
2125
- const compressionFlag = payload[0]; // 压缩标志
2126
2133
  const lengthBytes = payload.slice(1, 5); // 消息长度的4字节
2127
2134
  responseDataExpectedLength = new DataView(lengthBytes.buffer, lengthBytes.byteOffset).getUint32(0, false); // big-endian
2128
2135
  if (responseDataExpectedLength < 0) {
@@ -2199,7 +2206,7 @@ class Libp2pGrpcClient {
2199
2206
  const ackSettingFrame = Http2Frame.createSettingsAckFrame();
2200
2207
  writer.write(ackSettingFrame);
2201
2208
  };
2202
- parser.onHeaders = (headers, header) => {
2209
+ parser.onHeaders = (headers) => {
2203
2210
  const plainHeaders = hpack.decodeHeaderFields(headers);
2204
2211
  if (plainHeaders.get("grpc-status") === "0") {
2205
2212
  // 成功状态
@@ -2224,21 +2231,12 @@ class Libp2pGrpcClient {
2224
2231
  const settingFrme = Http2Frame.createSettingsFrame();
2225
2232
  await writer.write(settingFrme);
2226
2233
  // 等待对端 SETTINGS 或 ACK,择一即可,避免偶发握手竞态
2227
- {
2228
- let progressed = false;
2229
- await Promise.race([
2230
- (async () => {
2231
- await parser.waitForPeerSettings(1000);
2232
- progressed = true;
2233
- })(),
2234
- (async () => {
2235
- await parser.waitForSettingsAck();
2236
- progressed = true;
2237
- })(),
2238
- new Promise((res) => setTimeout(res, 300)),
2239
- ]);
2240
- // 即使未等到,也继续;多数实现会随后发送
2241
- }
2234
+ await Promise.race([
2235
+ parser.waitForPeerSettings(1000),
2236
+ parser.waitForSettingsAck(),
2237
+ new Promise((res) => setTimeout(res, 300)),
2238
+ ]);
2239
+ // 即使未等到,也继续;多数实现会随后发送
2242
2240
  // 创建头部帧
2243
2241
  const headerFrame = Http2Frame.createHeadersFrame(streamId, method, true, this.token);
2244
2242
  await writer.write(headerFrame);
@@ -2266,9 +2264,9 @@ class Libp2pGrpcClient {
2266
2264
  checkResponse();
2267
2265
  });
2268
2266
  try {
2269
- await writer.flush?.(timeout);
2267
+ await writer.flush(timeout);
2270
2268
  }
2271
- catch { }
2269
+ catch { /* ignore flush errors */ }
2272
2270
  await writer.end();
2273
2271
  }
2274
2272
  catch (err) {
@@ -2368,7 +2366,7 @@ class Libp2pGrpcClient {
2368
2366
  if (options?.freshConnection) {
2369
2367
  try {
2370
2368
  this.connectionPool.delete(this.peerAddr.toString());
2371
- await this.node?.hangUp?.(this.peerAddr);
2369
+ await this.node.hangUp(this.peerAddr);
2372
2370
  console.warn("[Call] hangUp existing connection before dialing due to freshConnection=true");
2373
2371
  }
2374
2372
  catch (err) {
@@ -2401,14 +2399,14 @@ class Libp2pGrpcClient {
2401
2399
  });
2402
2400
  try {
2403
2401
  writer.addEventListener("backpressure", (e) => {
2404
- const d = e?.detail || {};
2402
+ const d = e.detail || {};
2405
2403
  console.warn(`[stream ${streamId}] backpressure current=${d.currentSize} avg=${d.averageSize} threshold=${d.threshold}`);
2406
2404
  });
2407
- writer.addEventListener("drain", (e) => {
2408
- const d = e?.detail || {};
2405
+ writer.addEventListener("drain", () => {
2406
+ // drain event - no action needed
2409
2407
  });
2410
2408
  writer.addEventListener("stalled", (e) => {
2411
- const d = e?.detail || {};
2409
+ const d = e.detail || {};
2412
2410
  console.warn(`[stream ${streamId}] stalled queue=${d.queueSize} drained=${d.drained} since=${d.sinceMs}ms — sending PING`);
2413
2411
  try {
2414
2412
  const payload = new Uint8Array(8);
@@ -2416,10 +2414,10 @@ class Libp2pGrpcClient {
2416
2414
  const ping = Http2Frame.createFrame(0x6, 0x0, 0, payload);
2417
2415
  writer.write(ping);
2418
2416
  }
2419
- catch { /* empty */ }
2417
+ catch { /* ignore ping write errors */ }
2420
2418
  });
2421
2419
  }
2422
- catch { /* empty */ }
2420
+ catch { /* ignore addEventListener errors */ }
2423
2421
  const parser = new HTTP2Parser(writer, {
2424
2422
  compatibilityMode: !useFlowControl,
2425
2423
  });
@@ -2436,7 +2434,7 @@ class Libp2pGrpcClient {
2436
2434
  }
2437
2435
  internalController.abort();
2438
2436
  try {
2439
- connection?.close?.();
2437
+ connection?.close();
2440
2438
  }
2441
2439
  catch (err) {
2442
2440
  console.warn("Error closing connection after GOAWAY:", err);
@@ -2471,7 +2469,7 @@ class Libp2pGrpcClient {
2471
2469
  }
2472
2470
  };
2473
2471
  // 在各个回调中检查是否已中止
2474
- parser.onData = async (payload, frameHeader) => {
2472
+ parser.onData = async (payload) => {
2475
2473
  // 检查是否已中止
2476
2474
  if (internalController.signal.aborted) {
2477
2475
  return;
@@ -2491,7 +2489,6 @@ class Libp2pGrpcClient {
2491
2489
  // 如果还没有读取消息长度,且缓冲区有足够数据
2492
2490
  if (expectedMessageLength === -1 && messageBuffer.length >= 5) {
2493
2491
  // 读取 gRPC 消息头:1字节压缩标志 + 4字节长度
2494
- const compressionFlag = messageBuffer[0];
2495
2492
  const lengthBytes = messageBuffer.slice(1, 5);
2496
2493
  expectedMessageLength = new DataView(lengthBytes.buffer, lengthBytes.byteOffset).getUint32(0, false); // big-endian
2497
2494
  }
@@ -2528,7 +2525,7 @@ class Libp2pGrpcClient {
2528
2525
  const ackSettingFrame = Http2Frame.createSettingsAckFrame();
2529
2526
  writer.write(ackSettingFrame);
2530
2527
  };
2531
- parser.onHeaders = (headers, header) => {
2528
+ parser.onHeaders = (headers) => {
2532
2529
  // 检查是否已中止
2533
2530
  if (internalController.signal.aborted)
2534
2531
  return;
@@ -2574,16 +2571,9 @@ class Libp2pGrpcClient {
2574
2571
  }
2575
2572
  // 等待对端 SETTINGS 或 ACK,择一即可,避免偶发握手竞态
2576
2573
  {
2577
- let progressed = false;
2578
2574
  await Promise.race([
2579
- (async () => {
2580
- await parser.waitForPeerSettings(1000);
2581
- progressed = true;
2582
- })(),
2583
- (async () => {
2584
- await parser.waitForSettingsAck();
2585
- progressed = true;
2586
- })(),
2575
+ parser.waitForPeerSettings(1000),
2576
+ parser.waitForSettingsAck(),
2587
2577
  new Promise((res) => setTimeout(res, 300)),
2588
2578
  ]);
2589
2579
  // 即使未等到,也继续;多数实现会随后发送
@@ -2620,7 +2610,6 @@ class Libp2pGrpcClient {
2620
2610
  }
2621
2611
  // 动态批量处理逻辑 - 在处理过程中动态补充新数据
2622
2612
  const batchSize = options?.batchSize || 10;
2623
- const maxBatchWaitMs = options?.maxBatchWaitMs || 50;
2624
2613
  // 动态批处理器
2625
2614
  const processingQueue = [];
2626
2615
  let isProcessing = false;
@@ -2751,9 +2740,9 @@ class Libp2pGrpcClient {
2751
2740
  await writeFrame(finalFrame);
2752
2741
  // 在结束前尽量冲刷内部队列,避免服务器看到部分数据 + context canceled
2753
2742
  try {
2754
- await writer.flush?.(timeout);
2743
+ await writer.flush(timeout);
2755
2744
  }
2756
- catch { }
2745
+ catch { /* ignore flush errors */ }
2757
2746
  await writer.end();
2758
2747
  }
2759
2748
  // 检查是否已中止
@@ -2800,15 +2789,16 @@ class Libp2pGrpcClient {
2800
2789
  if (options?.freshConnection) {
2801
2790
  try {
2802
2791
  // 通过 libp2p 连接管理器关闭到该 peer 的连接
2803
- const conns = this.node?.getConnections?.(this.peerAddr) || [];
2792
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2793
+ const conns = this.node.getConnections?.(this.peerAddr) || [];
2804
2794
  for (const c of conns) {
2805
2795
  try {
2806
2796
  await c.close?.();
2807
2797
  }
2808
- catch { }
2798
+ catch { /* ignore close errors */ }
2809
2799
  }
2810
2800
  }
2811
- catch { }
2801
+ catch { /* ignore connection cleanup errors */ }
2812
2802
  }
2813
2803
  if (streamSlotAcquired && state) {
2814
2804
  state.activeStreams = Math.max(0, state.activeStreams - 1);