UNPKG

@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
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