Skip to content

fix: share one close across concurrent session and client close() calls - #607

Open
vuanhphung wants to merge 2 commits into
mainfrom
fix/concurrent-session-close
Open

vuanhphung wants to merge 2 commits into
mainfrom
fix/concurrent-session-close

Conversation

@vuanhphung

@vuanhphung vuanhphung commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

DBSQLSession.close() sets isOpen = false only after the CloseSession RPC returns, so concurrent callers all pass the open check and each send CloseSession for the same handle. DBSQLClient.close() has the same race: each concurrent call closes the sessions and releases the shared TelemetryClient refcount (TelemetryClientProvider.releaseClient), which can close the telemetry client still used by other DBSQLClients on the same host.

Found by the cross-driver session-lifecycle spec (SESSION-014, Concurrent Session Close: concurrent disposes must not throw and must send exactly one CloseSession). A live run against main through the test proxy showed 3 CloseSession requests for Promise.all([client.close(), client.close(), client.close()]) on Thrift. The kernel backend already sends one DeleteSession.

Change

close() on a session and on a client now returns the in-flight close to concurrent callers, so the work runs once and every caller gets the same result or error. The shared close is cleared when it settles, so a close that failed before CloseSession (for example an operation failed to close) can be retried, and a reconnected client can be closed again.

Verification

  • npm test (1755 passing), npm run lint, npm run prettier on the changed files.
  • New unit tests: one closeSession for concurrent session closes, a shared rejection when it fails, a retry after closing operations failed, and one CloseSession / backend close / telemetry release for concurrent client closes. Each fails without the change.
  • With this branch built, the databricks-driver-test SESSION-014 Thrift test (databricks/databricks-driver-test#2075) sends one CloseSession and its xfail tripwire throws XPASS; the other session-lifecycle tests still pass on Thrift and SEA.

This pull request and its description were written by Isaac.

DBSQLSession.close() marked the session closed only after the CloseSession
RPC returned, so concurrent callers each sent CloseSession for the same
handle. DBSQLClient.close() had the same race and released the shared
telemetry client once per caller. Both now return the in-flight close to
concurrent callers.

Co-authored-by: Isaac <no-reply@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 1 Medium

Mostly good: the shared in-flight close removes the duplicate CloseSession / telemetry-release race, and the tests cover it. One medium concern: the session's shared close promise is never cleared, so if closing one of its operations fails, that error is cached and the session can never be closed or retried.

Comment thread lib/DBSQLSession.ts Resolved
The shared session close was never cleared, so if closing the session's
operations rejected before CloseSession was sent, every later close()
returned the same rejection and the session could not be closed. Clear
the shared close once it settles, as DBSQLClient.close() already does.

Co-authored-by: Isaac <no-reply@databricks.com>
Signed-off-by: Vu Anh Phung <vu.phung@databricks.com>

@peco-review-bot peco-review-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No issues identified by the review bot.

@vuanhphung

Copy link
Copy Markdown
Collaborator Author

The red Node.js Integration Tests check is expected. Run 43393988622 tested defd9b9 against databricks/databricks-driver-test#2075. On Thrift, the only failure is that PR's SESSION-014 tripwire throwing XPASS: concurrent closes now send one CloseSession, and the xfail goes away once this merges. On SEA, TELEMETRY-003/015 failed on warehouse timing; both pass locally on defd9b9 and passed in the main run (43393984906). Every session-lifecycle test passed on both backends.

This comment was written by Isaac.

This branch had an error being deployed

1 failed deployment
azure-prod — defd9b94 Deployed Nov 13, 2026 by vuanhphung via e2e-test (26.12.1, 26_12_1) #2001
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant