> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 处理解析流中的重连和错误

> 检测解析流断开连接，使用退避策略重新连接，重新订阅，并准确回填您错过的槽窗口。

传递是**最多一次** — 没有重播。在断开连接时已确认的内容不会重新发送，因此生产客户端需要检测缺口并决定是否进行补填。其信号是 `context.slot`：它界定了断开连接时错过的窗口。本指南涵盖了连接为何关闭、如何干净地重新连接以及如何使用它。

## 为什么连接会关闭

每次关闭都有一个 WebSocket 关闭代码，告诉您发生了什么以及接下来该怎么做：

| 代码          | 原因                | 应对措施                                                                              |
| ----------- | ----------------- | --------------------------------------------------------------------------------- |
| 1000        | 空闲：10分钟没有客户端消息和通知 | 如果您的过滤器安静，可以每隔几分钟发送 JSON-RPC `ping` 方法。客户端库自动发送的协议级 WebSocket ping **不会**重置空闲计时器。 |
| 1001        | 服务器重启（部署）         | 重新连接并重新订阅                                                                         |
| 1008        | 慢消费者：您落后超过2048个通知 | 用较窄的过滤器重新连接，`details: "matched"` 或 `"raw"`，或更快的处理                                 |
| 1005 / 1006 | 网络边缘回收了连接         | 重新连接并重新订阅；在任何长连接中都有一定频率正常发生                                                       |

服务器每15秒发送一次 ping，因此健康但安静的连接仍然会有流量。如果超过一分钟完全没有看到任何东西——没有通知，没有 ping——假定连接已断开，并重新连接，而不是等待套接字告诉您。

## 保持连接活跃

如果你的过滤器足够窄，可以合法地在10分钟内没有匹配，则在比这个时间间隔更短的时间内发送一个明确的 JSON-RPC `ping`：

```json theme={"system"}
{ "jsonrpc": "2.0", "id": 99, "method": "ping" }
```

它返回当前的 slot，更重要的是，它算作闲置计时器的客户端消息。库级别的 WebSocket ping 帧则不算。

## 重新连接并检测间隙

<Steps>
  <Step title="带退避的重新连接">
    无论任何关闭——预期的或非预期的——都使用指数退避重新连接。订阅 ID 无法在重新连接中保留，因此请为您打开的每个过滤器重新发送 `parsedTransactionSubscribe`。
  </Step>

  <Step title="跟踪跨断开的 context.slot">
    保留您在断开连接前看到的最后一个 `context.slot`。在该插槽与重新连接后看到的第一个插槽之间的差距正是您错过的窗口——不多不少。
  </Step>

  <Step title="如果需要，请进行补填">
    如果您的应用程序无法容忍此差距，请从 RPC 填补该插槽窗口：使用 `getSignaturesForAddress` 枚举范围内的交易，然后使用 `getTransaction` 获取每个交易。这是一个手动对帐步骤——Parsed Streams 本身不进行重播。
  </Step>
</Steps>

```typescript theme={"system"}
import WebSocket from "ws";

const URL = "wss://<ENDPOINT>/?api-key=<API_KEY>";
const filters = [
  { programs: ["JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"] },
];

let lastSlotSeen: number | null = null;
let backoffMs = 1000;

function connect() {
  const ws = new WebSocket(URL);

  ws.on("open", () => {
    backoffMs = 1000;
    filters.forEach((filter, i) => {
      ws.send(JSON.stringify({
        jsonrpc: "2.0",
        id: i + 1,
        method: "parsedTransactionSubscribe",
        params: [filter],
      }));
    });
  });

  ws.on("message", (data) => {
    const msg = JSON.parse(data.toString());
    if (msg.method === "parsedTransactionNotification") {
      const { slot } = msg.params.result.context;

      // Across reconnects, the slot bounds the backfill window.
      if (lastSlotSeen !== null && slot > lastSlotSeen) {
        // backfill candidates: slots lastSlotSeen+1 .. slot-1 while disconnected
      }
      lastSlotSeen = slot;
    }
  });

  ws.on("close", (code) => {
    console.warn(`connection closed (${code}); reconnecting in ${backoffMs}ms`);
    setTimeout(connect, backoffMs);
    backoffMs = Math.min(backoffMs * 2, 30_000);
  });
}

connect();
```

`context.slot` 是重新连接后仍然存在的内容：跟踪断开连接前您已完全处理的最高插槽，并将其后的所有内容视作补填窗口。

## 处理 JSON-RPC 错误

失败的请求会返回 JSON-RPC 错误而不是结果，因此你可以基于 `error.code` 进行分支：

| Code     | 含义                         |
| -------- | -------------------------- |
| `-32700` | 解析错误（无效的JSON）              |
| `-32600` | 无效请求                       |
| `-32601` | 方法未找到                      |
| `-32602` | 无效参数：错误的公钥、未知字段、不支持的承诺或详情值 |
| `-32000` | 过滤器限制超出                    |
| `-32001` | 服务器未准备好；重试并退避              |
| `-32002` | 速率限制（每秒10条消息）              |
| `-32006` | 订阅过多（每个连接25个）              |

`-32602` 和 `-32000` 意味着请求本身有误—修复过滤器，不要重试相同请求。`-32001` 和 `-32002` 是暂时的；使用与重连接相同的退避重试。

## 下一步

<CardGroup cols={2}>
  <Card title="快速开始" icon="bolt" href="/docs/zh/parsed-streams/quickstart">
    完整协议参考：方法、过滤器字段、限制。
  </Card>

  <Card title="跟踪Jupiter互换" icon="arrow-right-arrow-left" href="/docs/zh/parsed-streams/guides/track-jupiter-swaps">
    构建此连接可以订阅的过滤器。
  </Card>
</CardGroup>
