CritasWang opened a new pull request, #63:
URL: https://github.com/apache/iotdb-client-csharp/pull/63
Addresses the third issue raised in #61 (the `IsOpen()` semantics
discussion). Complements #62, which
fixes the two blocking defects; this PR adds the API that was deliberately
left out of that one to keep it
focused on the bugs.
对应 #61 中提出的第三个议题(`IsOpen()` 语义讨论)。与 #62 互补:#62 修复两个导致阻塞的缺陷,本 PR 新增
当时为保持该 PR 聚焦于缺陷而刻意剥离的 API。
## Why / 背景
`IsOpen()` is `!_isClose`, and `_isClose` only flips on explicit `Open()` /
`Close()`. The client keeps no
heartbeat, so a server going down never changes it. That is working as
designed and matches the Java
client — but the name reads like a health check, and users write guards such
as:
`IsOpen()` 即 `!_isClose`,只有显式 `Open()` / `Close()` 会改变它;客户端无心跳,服务端断开不会回写。
这是符合设计的(与 Java 客户端一致),但这个命名读起来像健康检查,于是用户会写出这样的守卫:
```csharp
// Never re-opens: IsOpen() stays true even while every connection is dead
if (_pool != null && _pool.IsOpen()) return;
```
Rather than change `IsOpen()` — which would be a silent behavioural break
for anyone relying on the
lifecycle meaning — this PR adds the connectivity check it is mistaken for.
与其修改 `IsOpen()`(会对依赖其生命周期语义的使用方造成无声的行为破坏),本 PR 选择新增它被误认为具备的
连通性检查能力。
## What / 实现
`SessionPool.CheckHealthAsync(CancellationToken)` issues one lightweight
request on an idle pooled
connection and returns a `SessionPoolHealth` snapshot (`Status`,
`AvailableClients`, `TotalPoolSize`,
`FailedReconnections`, `Message`, `Error`).
`SessionPool.CheckHealthAsync(CancellationToken)` 在空闲连接上发送一次轻量请求,返回
`SessionPoolHealth`
快照(状态、可用连接数、池容量、重连失败次数、说明、底层异常)。
```csharp
var health = await sessionPool.CheckHealthAsync();
if (!health.IsHealthy)
{
logger.LogWarning("{Health}", health); // "Unhealthy: The server did
not answer the probe: ..."
}
```
| `SessionPoolHealthStatus` | Meaning / 含义
|
| - |
-
|
| `NotOpen` | Pool not opened, or already closed. No network
call is attempted. 池未打开或已关闭,不发起网络调用 |
| `Healthy` | The server answered the probe. 服务端已响应探测
|
| `Degraded`| Open, but no idle connection to probe with.
已打开但无空闲连接可探测 |
| `Unhealthy` | A connection was available but the server did
not answer. 有可用连接但服务端未响应|
Design decisions worth reviewing / 需要评审关注的设计决策:
- **The probe never blocks.** `ConcurrentClientQueue.TryTake` is added for
this. A health endpoint must not
queue behind application load, so when every client is busy the probe
returns `Degraded` at once rather
than waiting. This also keeps the probe independent of the pool wait
timeout fixed in #62.
**探针永不阻塞**:为此新增 `ConcurrentClientQueue.TryTake`。健康检查端点不应排在业务负载之后,所以所有
连接繁忙时立即返回 `Degraded`。这也使探针不依赖 #62 中修复的池等待超时。
- **`Degraded` is deliberately not a server verdict.** It only means nothing
was idle at that instant.
Treating saturation as an outage would make the check useless under load.
**`Degraded` 刻意不表示服务端故障**,只表示当时没有空闲连接。把饱和当作故障会让该检查在高负载下失去意义。
- **The borrowed connection is always returned, and a failed probe does not
close it.** The existing
reconnect-on-use path still handles the dead connection on the next real
operation, so the probe has no
side effects on pool state.
**借出的连接总会归还,探测失败也不关闭它**:失效连接仍由既有的按需重连路径在下次真实操作时处理,探针
对池状态无副作用。
- **No implicit timeout.** Callers bound the probe with a
`CancellationToken` if they want to; adding a
hidden default felt worse than making it explicit. Happy to add one if
reviewers disagree.
**不设隐式超时**:调用方可用 `CancellationToken` 自行限时。相比隐藏的默认值,显式更好。若评审有不同
意见,可以加上。
`TableSessionPool` forwards the method with identical semantics.
`TableSessionPool` 以相同语义转发该方法。
## Relationship to #62 / 与 #62 的关系
Both branch from `main` and are independently mergeable. They touch
`ConcurrentClientQueue.cs`,
`SessionPool.cs` and the same two docs, so whichever merges second will need
a trivial rebase — the changes
are additive and do not overlap semantically (#62 fixes the wait timeout and
slot accounting; this PR adds
a probe path).
两者均基于 `main` 且可独立合并。它们都改动了 `ConcurrentClientQueue.cs`、`SessionPool.cs` 和同样的两份
文档,因此后合并的一方需要一次简单的 rebase——改动是叠加式的、语义上不重叠(#62 修复等待超时与槽位记账,
本 PR 新增探测路径)。
Suggested order: merge #62 first (it fixes user-facing hangs), then rebase
this one.
建议顺序:先合并 #62(它修复的是用户可见的卡死),再 rebase 本 PR。
## Tests / 测试
`SessionPoolHealthTests` covers the `NotOpen` path (asserting no network
call is attempted and the call
returns promptly), the non-blocking