Add SessionPool.CheckHealthAsync connectivity probe 新增 SessionPool.CheckHealthAsync 连通性探针 - #63
Open
CritasWang wants to merge 1 commit into
Open
Conversation
CritasWang
force-pushed
the
feat/session-pool-health-check
branch
from
July 31, 2026 04:47
e985874 to
6e27d52
Compare
新增 SessionPool.CheckHealthAsync 连通性探针 IsOpen() is a lifecycle flag - it reports whether the caller has opened the pool and not yet closed it. Because the client keeps no heartbeat, it stays true after the server goes down, and users routinely mistake it for a health check, e.g. `if (pool.IsOpen()) return;` in a lazy-open guard, which then never rebuilds the pool. This adds the connectivity check that IsOpen() is mistaken for, without changing IsOpen() itself. IsOpen() 是生命周期标志,仅表示调用方是否已打开且尚未关闭连接池。由于客户端无心跳, 服务端断开后它仍为 true,用户普遍将其误当作健康检查(例如惰性打开守卫里的 `if (pool.IsOpen()) return;`),从而导致连接池永远不会被重建。本提交新增了 IsOpen() 被误认为具备的连通性检查能力,且不改变 IsOpen() 自身行为。 - Add SessionPool.CheckHealthAsync(CancellationToken), which issues one lightweight request on an idle pooled connection and returns a SessionPoolHealth snapshot carrying Status, AvailableClients, TotalPoolSize, FailedReconnections, Message and the underlying Error. 新增 SessionPool.CheckHealthAsync(CancellationToken):在空闲连接上发送一次轻量请求, 返回包含状态、可用连接数、池容量、重连失败次数、说明和底层异常的 SessionPoolHealth 快照。 - Add SessionPoolHealthStatus with four outcomes: NotOpen (no network call is made), Healthy, Degraded (open but no idle connection to probe with - a saturation signal, not a server verdict) and Unhealthy (a connection was available but the server did not answer). 新增 SessionPoolHealthStatus 四种结果:NotOpen(不发起网络调用)、Healthy、 Degraded(池已打开但无空闲连接可用于探测,表示饱和而非服务端故障)、 Unhealthy(有可用连接但服务端未响应)。 - Add ConcurrentClientQueue.TryTake so the probe never blocks. A health endpoint must not queue behind application load, so when every client is busy the probe returns Degraded immediately instead of waiting. 新增 ConcurrentClientQueue.TryTake 使探针永不阻塞:健康检查端点不应排在业务负载之后, 因此所有连接繁忙时立即返回 Degraded 而不是等待。 - The borrowed connection is always returned to the pool and a failed probe does not close it, so the existing reconnect-on-use path is unchanged. 借出的连接总会归还池中,探测失败也不会关闭它,因此既有的按需重连路径保持不变。 - Forward CheckHealthAsync from TableSessionPool with identical semantics. TableSessionPool 以相同语义转发 CheckHealthAsync。 - Add tests for the NotOpen path, non-blocking TryTake semantics and the health snapshot; document the API in docs/SessionPool_Exception_Handling.md and docs/API.md. 补充 NotOpen 路径、TryTake 非阻塞语义与健康快照的测试;在相关文档中说明该 API。
CritasWang
force-pushed
the
feat/session-pool-health-check
branch
from
July 31, 2026 10:22
6e27d52 to
03b3bf7
Compare
Contributor
Author
|
Rebased onto #62 was squash-merged, so the three commits this branch previously carried no longer matched upstream and GitHub started reporting a conflict. I rebased with Verified locally against merged Ready for review. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Addresses the third issue raised in #61 (the
IsOpen()semantics discussion). Complements #62, whichfixes 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_isCloseonly flips on explicitOpen()/Close(). The client keeps noheartbeat, 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 客户端一致),但这个命名读起来像健康检查,于是用户会写出这样的守卫:
Rather than change
IsOpen()— which would be a silent behavioural break for anyone relying on thelifecycle meaning — this PR adds the connectivity check it is mistaken for.
与其修改
IsOpen()(会对依赖其生命周期语义的使用方造成无声的行为破坏),本 PR 选择新增它被误认为具备的连通性检查能力。
What / 实现
SessionPool.CheckHealthAsync(CancellationToken)issues one lightweight request on an idle pooledconnection and returns a
SessionPoolHealthsnapshot (Status,AvailableClients,TotalPoolSize,FailedReconnections,Message,Error).SessionPool.CheckHealthAsync(CancellationToken)在空闲连接上发送一次轻量请求,返回SessionPoolHealth快照(状态、可用连接数、池容量、重连失败次数、说明、底层异常)。
SessionPoolHealthStatusNotOpenHealthyDegradedUnhealthyDesign decisions worth reviewing / 需要评审关注的设计决策:
ConcurrentClientQueue.TryTakeis added for this. A health endpoint must notqueue behind application load, so when every client is busy the probe returns
Degradedat once ratherthan waiting. This also keeps the probe independent of the pool wait timeout fixed in Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62.
探针永不阻塞:为此新增
ConcurrentClientQueue.TryTake。健康检查端点不应排在业务负载之后,所以所有连接繁忙时立即返回
Degraded。这也使探针不依赖 Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62 中修复的池等待超时。Degradedis 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刻意不表示服务端故障,只表示当时没有空闲连接。把饱和当作故障会让该检查在高负载下失去意义。reconnect-on-use path still handles the dead connection on the next real operation, so the probe has no
side effects on pool state.
借出的连接总会归还,探测失败也不关闭它:失效连接仍由既有的按需重连路径在下次真实操作时处理,探针
对池状态无副作用。
CancellationTokenif they want to; adding ahidden default felt worse than making it explicit. Happy to add one if reviewers disagree.
不设隐式超时:调用方可用
CancellationToken自行限时。相比隐藏的默认值,显式更好。若评审有不同意见,可以加上。
TableSessionPoolforwards the method with identical semantics.TableSessionPool以相同语义转发该方法。Relationship to #62 / 与 #62 的关系
#62 is now merged (
178ebb0), and this branch has been rebased onto it. Because #62 was squash-merged, thethree commits this branch previously carried no longer matched upstream and GitHub reported a conflict; I
rebased with
--onto upstream/mainso only the health-check commit remains. This PR is now a singlecommit against current
mainwith no conflicts.#62 已合并(
178ebb0),本分支已 rebase 到其之上。由于 #62 采用 squash 合并,本分支原先携带的三个提交与上游不再匹配,GitHub 因此报告冲突;我使用
--onto upstream/main进行 rebase,只保留健康检查这一个提交。本 PR 现在是基于当前
main的单个提交,无冲突。The overlaps with #62 were resolved during the earlier rebase and carried through:
与 #62 的重叠已在此前的 rebase 中解决并延续至今:
ConcurrentClientQueue—TryTakesits alongside Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62'sTimeoutInMsand the obsoleteTimeoutshim;the tests set
TimeoutInMs.TryTake与 Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62 的TimeoutInMs及过时的Timeout兼容属性并存;测试使用TimeoutInMs。IsOpen()XML docs — points atCheckHealthAsyncfor connectivity and at the pool-state properties(including Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62's
UnrealizedCapacity) for diagnostics.同时指向
CheckHealthAsync(连通性)与池状态属性(诊断,含 Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62 的UnrealizedCapacity)。docs/SessionPool_Exception_Handling.md— theCheckHealthAsyncvsIsOpensection sits next to Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62's"Pool Wait Timeout" section, and notes that the probe is unaffected by that timeout.
CheckHealthAsync与IsOpen的对比章节与 Fix SessionPool blocking indefinitely after a server outage 修复服务端断开后 SessionPool 永久阻塞的问题 #62 的 "Pool Wait Timeout" 章节并列,并说明探针不受该超时影响。Tests / 测试
SessionPoolHealthTestscovers theNotOpenpath (asserting no network call is attempted and the callreturns promptly), the non-blocking
TryTakesemantics, and theSessionPoolHealthsnapshot itself.SessionPoolHealthTests覆盖NotOpen路径(断言不发起网络调用且立即返回)、TryTake的非阻塞语义,以及
SessionPoolHealth快照本身。dotnet test tests/Apache.IoTDB.Tests— 29 passed, 0 failed.dotnet build Apache.IoTDB.sln— 0 errors.dotnet format --verify-no-changes— clean.The
Healthy/Unhealthytransitions need a live server and are left to the e2e suite rather thansimulated with a mock transport.
Healthy/Unhealthy的状态转换需要真实服务端,交由 e2e 套件覆盖,未用 mock transport 模拟。Note: the unit tests were executed locally against
net8.0because no .NET 5 arm64 runtime is available onthis machine; the committed
TargetFrameworkis unchanged atnet5.0.说明:本机没有 .NET 5 的 arm64 运行时,单元测试在本地以
net8.0执行;提交的TargetFramework仍为net5.0。Docs / 文档
docs/SessionPool_Exception_Handling.md— new section contrastingCheckHealthAsyncwithIsOpen, thestatus table, behaviour notes, and the existing health-check example rewritten to delegate to the
built-in probe.
docs/SessionPool_Exception_Handling.md—— 新增对比CheckHealthAsync与IsOpen的章节、状态表、行为说明,并将原有的健康检查示例改写为委托给内置探针。
docs/API.md— added theCheckHealthAsyncrow and clarifiedIsOpen.docs/API.md—— 新增CheckHealthAsync一行并澄清IsOpen。