All files / packages/core/src conn.ts

88.88% Statements 8/9
100% Branches 0/0
75% Functions 3/4
88.88% Lines 8/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76                      55x                                                   2104x       2104x             2104x   2104x                 1806x       2082x         2082x              
import type { EndpointInfo as ProtoEndpointInfo } from '@ydbjs/api/discovery'
import { loggers } from '@ydbjs/debug'
import {
	type Channel,
	type ChannelCredentials,
	type ChannelOptions,
	createChannel,
} from 'nice-grpc'
 
import type { EndpointInfo } from './hooks.js'
 
let dbg = loggers.driver.extend('conn')
 
/**
 * Immutable view of a single gRPC connection.
 * Pessimization state is owned by the Pool — not here.
 */
export interface Connection extends Disposable {
	readonly endpoint: EndpointInfo
	readonly channel: Channel
 
	close(): void
	[Symbol.dispose](): void
}
 
/**
 * A single gRPC connection to a YDB node.
 */
export class GrpcConnection implements Connection {
	readonly endpoint: EndpointInfo
	#channel: Channel
 
	constructor(
		endpoint: ProtoEndpointInfo,
		channelCredentials: ChannelCredentials,
		channelOptions?: ChannelOptions
	) {
		let address = `${endpoint.address}:${endpoint.port}`
 
		// Freeze the value object so hooks receive a stable, immutable reference
		// without being able to accidentally mutate driver internals.
		this.endpoint = Object.freeze<EndpointInfo>({
			nodeId: BigInt(endpoint.nodeId),
			address,
			location: endpoint.location,
			pile: endpoint.bridgePileName,
		})
 
		dbg.log('create channel to node id=%d address=%s', this.endpoint.nodeId, address)
 
		this.#channel = createChannel(address, channelCredentials, {
			...channelOptions,
			// Required when the TLS certificate CN doesn't match the gRPC endpoint
			// address (common in YDB deployments behind a load balancer).
			'grpc.ssl_target_name_override': endpoint.sslTargetNameOverride,
		})
	}
 
	get channel(): Channel {
		return this.#channel
	}
 
	close(): void {
		dbg.log(
			'close channel to node id=%d address=%s',
			this.endpoint.nodeId,
			this.endpoint.address
		)
		this.#channel.close()
	}
 
	[Symbol.dispose](): void {
		this.close()
	}
}