Hi all,

While working with the nodejs client, I audited the session pool and
connection lifecycle in iotdb-client-nodejs and found seven related
issues. Before sending patches I'd like to share the findings and the
fix plan here, and get input on one design question.

Findings (all reproduced with unit tests against develop):

Acquisition path (BaseSessionPool.getSession):

1. A timed-out waiter is never removed from the wait queue: the timeout
handler searches the queue for the resolve function, but the queue
stores a wrapper closure, so the lookup never matches. A later
releaseSession then hands the session to the dead waiter, the session
is marked in-use forever, and the pool starves.

2. The create-new-session branch removes the wrong idle entry under
interleaving: it does a blind shift() from the front after an await,
while createSession pushes the new session to the back. A session
released into the idle queue during the await gets evicted instead,
and the new session ends up tracked as both idle and active.

3. The idle-reuse branch never sets inUse = true (the new-session and
waiter branches both do), so syncDatabaseContextToPool, which filters
on !inUse, can run "USE <db>" on a session that is mid-request for
another caller.

Cleanup path (cleanupIdleSessions):

4. The minPoolSize guard is evaluated against the pre-cleanup pool size,
so one cleanup round can retire every idle session and shrink the
pool below minPoolSize (down to zero).

5. Sessions are closed before being removed from the idle queue, and
isOpen() stays true until the async close completes, so a concurrent
getSession() can be handed a session that is being destroyed.

Connection:

6. Connection.open() leaks the established socket and its listeners when
openSession/requestStatementId fails after the TCP connect succeeded;
through the pool, each failed connect attempt leaks one socket.

Design question (redirect sessions):

7. With enableRedirection, a session created for a redirect endpoint is
tracked in endPointToSession AND ends up in the general idle queue
after release, so a plain getSession() and a redirect insert can
drive the same Thrift socket concurrently. Two possible directions:
(a) keep endpoint-owned sessions out of the general pool entirely, or
(b) route their release back to the endpoint cache instead of the
idle queue. Which of the two matches the intended redirect-reuse
design?

Fix plan: I have fixes for 1-6 ready with regression tests (each test
fails on current develop and passes with the fix; the full unit suite is
green). I would propose landing them as two focused PRs, one for the
pool lifecycle (1-5, they share a test harness) and one for the
connection open leak (6), and holding 7 for whichever direction the
maintainers prefer. The same pool-misuse pattern also affects
iotdb-mcp-server in tree mode (sessions are returned with close()
instead of put_back(), which exhausts the pool after max_pool_size
queries); I can follow up there once the approach here is agreed.

Feedback welcome - happy to adjust the scope or split differently.

Best,
Zihan Dai

Reply via email to