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