Skip to content

Add session pool for query service#556

Open
r142f wants to merge 3 commits intoydb-platform:mainfrom
r142f:query-session-pool
Open

Add session pool for query service#556
r142f wants to merge 3 commits intoydb-platform:mainfrom
r142f:query-session-pool

Conversation

@r142f
Copy link

@r142f r142f commented Feb 2, 2026

What

Add session pool for query service to reuse sessions between queries and transactions.

Why

Every query currently creates a new session, which is inefficient and increases load on YDB server. Session pooling eliminates this overhead.

Changes

  • Implement Session class with IDLE/BUSY/CLOSED states, handling creation and deletion of a session
  • Implement SessionPool with acquire/release pattern, FIFO wait queue, and configurable maxSize (default: 50)
  • Integrate SessionPool with Query class and transaction execution
  • Update README with session pool description

Testing

  • Added unit tests for SessionPool
  • Added integration tests for session reuse scenarios

Checklist

  • Changeset added (if package changes)
  • README updated (if public API changed)

- Implement Session class with IDLE/BUSY/CLOSED states and attachSession keepalive
- Implement SessionPool with acquire/release pattern (default maxSize: 50)
- Integrate SessionPool with Query class and transaction execution
- Add 13 new tests (7 unit + 6 integration)

Sessions are now automatically pooled and reused between queries and transactions,
eliminating the overhead of creating a new session for every operation.

Public API: query(driver, { maxSize?: number })
@r142f r142f force-pushed the query-session-pool branch from d257df8 to 68db0d5 Compare February 2, 2026 07:38
driver: Driver,
sessionId: string,
nodeId: bigint,
attachIterator?: AsyncIterator<SessionStateProto>
Copy link
Member

Choose a reason for hiding this comment

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

Итератор лучше создавать внутри класса, плюс аттач нужно делать только тогда, когда сессия в первый раз запросили.

Далее, закрытие стрима лучше делать через signal от AbortController();

Copy link
Author

Choose a reason for hiding this comment

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

Кажется, поправил
Еще добавил читателя для attach stream и состояние invalidated для обработки ошибок


test('executes simple query', async () => {
let sql = query(driver)
sql = query(driver)
Copy link
Member

Choose a reason for hiding this comment

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

можно просто using использовать

Copy link
Author

Choose a reason for hiding this comment

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

поправил

- Add INVALIDATED state and onInvalidated callback
- Add attach stream monitoring in background
- Lazy attach initialization in acquire()
- Support AbortSignal for cancellable attach
export function query(driver: Driver): QueryClient {
export function query(
driver: Driver,
poolOptions?: SessionPoolOptions
Copy link
Member

Choose a reason for hiding this comment

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

Лучше сделать отдельный QueryOptions и туда передать poolOptions

Copy link
Author

Choose a reason for hiding this comment

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

Поправил

)
}
dbg.log('acquiring session from pool for transaction')
let session = await sessionPool.acquire(signal)
Copy link
Member

Choose a reason for hiding this comment

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

по возможности, я бы хотел видеть using session = await sessionPool.acquire(signal) чтобы не потерять где-то ниже release. в го есть удобный defer, тут есть такой механизм.

Copy link
Author

Choose a reason for hiding this comment

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

вроде как поправил, теперь acquire возвращает обертку SessionLease

* Wait for a session to become available
*/
#waitForSession(signal?: AbortSignal): Promise<Session> {
return new Promise<Session>((resolve, reject) => {
Copy link
Member

Choose a reason for hiding this comment

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

Promise.withResolvers()

Copy link
Author

Choose a reason for hiding this comment

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

Заиспользовал

Comment on lines 180 to 182
while (this.#attachIterator) {
// eslint-disable-next-line no-await-in-loop
let result = await this.#attachIterator.next()
Copy link
Member

Choose a reason for hiding this comment

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

Посмотри на конструкцию for await при работе с асинхронным итераторами

Copy link
Author

Choose a reason for hiding this comment

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

Кажется, поправил

- Add SessionLease class with Symbol.dispose
- Use 'using' pattern in query execution and transactions
- Use for await...of and Promise.withResolvers()
- Add QueryOptions type and update documentation
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.

2 participants