@ydbjs/core
Version:
Core driver for YDB: manages connections, endpoint discovery, authentication, and service client creation. Foundation for all YDB client operations.
79 lines • 3.51 kB
TypeScript
import type { ChannelInterface as Channel } from '@grpc/grpc-js';
import type { DriverHooks } from './hooks.ts';
import type { ConnectionPool } from './pool.ts';
/**
* A grpc-js Channel implementation that routes each RPC to a connection
* selected by ConnectionPool.
*
* ## Why BalancedChannel instead of a Proxy?
*
* A Proxy on a Channel intercepts ALL property accesses and cannot bind
* a specific connection to the RPC being dispatched. BalancedChannel
* overrides createCall() — the single method grpc-js calls exactly once
* per RPC — and acquires a connection there.
*
* ## How it works
*
* 1. nice-grpc calls createCall() once per RPC (unary or stream).
* 2. We acquire a connection from the pool (round-robin or preferred nodeId).
* 3. We delegate createCall() to the real grpc-js Channel on that connection.
* 4. We return a Proxy-wrapped Call that intercepts start() to observe
* onReceiveStatus — the single callback grpc-js fires when the RPC ends.
* 5. On UNAVAILABLE: pessimize the connection so the next acquire() skips it.
* 6. Fire telemetry hooks in the original async context (AsyncLocalStorage).
*
* ## Async context preservation
*
* onReceiveStatus fires from the HTTP/2 event loop via process.nextTick(),
* which loses AsyncLocalStorage context. We capture it at createCall() time
* with AsyncLocalStorage.snapshot() and restore it in onReceiveStatus.
* This makes trace.getActiveSpan() work inside the onCall completion callback.
*
* ## grpc-js version pinning
*
* This class touches four grpc-js internal contact points:
* Channel.createCall(method, deadline, host, parentCall, propagateFlags) → Call
* Call.start(metadata, listener)
* listener.onReceiveStatus(status)
* status.code
*
* These are exported but not formally documented as stable public API.
* The grpc-js version MUST be pinned in peerDependencies of @ydbjs/core.
*/
export declare class BalancedChannel implements Channel {
#private;
constructor(pool: ConnectionPool, hooks?: DriverHooks, nodeId?: bigint);
createCall(...args: Parameters<Channel['createCall']>): ReturnType<Channel['createCall']>;
/**
* No-op: pool lifecycle is managed by Driver, not by individual clients.
* nice-grpc calls close() on the channel when a client is destroyed, but
* BalancedChannel does not own the pool.
*/
close(): void;
/**
* Returns the address of the first active connection (best-effort).
* Used by grpc-js for logging and error messages only.
*/
getTarget(): string;
/**
* Returns READY if the pool has any usable connections (active or pessimized),
* TRANSIENT_FAILURE otherwise.
*
* The tryToConnect flag is intentionally ignored — connection management is
* handled by grpc-js internally for each GrpcConnection channel.
*/
getConnectivityState(_tryToConnect: boolean): any;
/**
* Fires the callback on the next tick.
*
* watchConnectivityState is only used by Channel.waitForReady(), which is not
* called in pool mode (Driver.ready() uses its own mechanism). We provide a
* minimal implementation to satisfy the interface.
*/
watchConnectivityState(_currentState: any, _deadline: Date | number, callback: (error?: Error) => void): void;
/**
* Returns a stub ChannelzRef. We do not participate in channelz.
*/
getChannelzRef(): ReturnType<Channel['getChannelzRef']>;
}
//# sourceMappingURL=channel.d.ts.map