UNPKG

@electric-sql/pglite-socket

Version:

A socket implementation for PGlite enabling remote connections

1 lines 43.7 kB
{"version":3,"sources":["../../src/scripts/server.ts","../../src/index.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { PGlite, DebugLevel } from '@electric-sql/pglite'\nimport { PGLiteSocketServer } from '../index'\nimport { parseArgs } from 'node:util'\nimport { spawn, ChildProcess } from 'node:child_process'\n\n// Define command line argument options\nconst args = parseArgs({\n options: {\n db: {\n type: 'string',\n short: 'd',\n default: 'memory://',\n help: 'Database path (relative or absolute). Use memory:// for in-memory database.',\n },\n port: {\n type: 'string',\n short: 'p',\n default: '5432',\n help: 'Port to listen on',\n },\n host: {\n type: 'string',\n short: 'h',\n default: '127.0.0.1',\n help: 'Host to bind to',\n },\n path: {\n type: 'string',\n short: 'u',\n default: undefined,\n help: 'unix socket to bind to. Takes precedence over host:port',\n },\n debug: {\n type: 'string',\n short: 'v',\n default: '0',\n help: 'Debug level (0-5)',\n },\n run: {\n type: 'string',\n short: 'r',\n default: undefined,\n help: 'Command to run after server starts',\n },\n 'include-database-url': {\n type: 'boolean',\n default: false,\n help: 'Include DATABASE_URL in the environment of the subprocess',\n },\n 'shutdown-timeout': {\n type: 'string',\n default: '5000',\n help: 'Timeout in milliseconds for graceful subprocess shutdown (default: 5000)',\n },\n help: {\n type: 'boolean',\n short: '?',\n default: false,\n help: 'Show help',\n },\n },\n})\n\nconst help = `PGlite Socket Server\nUsage: pglite-server [options]\n\nOptions:\n -d, --db=PATH Database path (default: memory://)\n -p, --port=PORT Port to listen on (default: 5432)\n -h, --host=HOST Host to bind to (default: 127.0.0.1)\n -u, --path=UNIX Unix socket to bind to (default: undefined). Takes precedence over host:port\n -v, --debug=LEVEL Debug level 0-5 (default: 0)\n -r, --run=COMMAND Command to run after server starts\n --include-database-url Include DATABASE_URL in subprocess environment\n --shutdown-timeout=MS Timeout for graceful subprocess shutdown in ms (default: 5000)\n`\n\ninterface ServerConfig {\n dbPath: string\n port: number\n host: string\n path?: string\n debugLevel: DebugLevel\n runCommand?: string\n includeDatabaseUrl: boolean\n shutdownTimeout: number\n}\n\nclass PGLiteServerRunner {\n private config: ServerConfig\n private db: PGlite | null = null\n private server: PGLiteSocketServer | null = null\n private subprocessManager: SubprocessManager | null = null\n\n constructor(config: ServerConfig) {\n this.config = config\n }\n\n static parseConfig(): ServerConfig {\n return {\n dbPath: args.values.db as string,\n port: parseInt(args.values.port as string, 10),\n host: args.values.host as string,\n path: args.values.path as string,\n debugLevel: parseInt(args.values.debug as string, 10) as DebugLevel,\n runCommand: args.values.run as string,\n includeDatabaseUrl: args.values['include-database-url'] as boolean,\n shutdownTimeout: parseInt(args.values['shutdown-timeout'] as string, 10),\n }\n }\n\n private createDatabaseUrl(): string {\n const { host, port, path } = this.config\n\n if (path) {\n // Unix socket connection\n const socketDir = path.endsWith('/.s.PGSQL.5432')\n ? path.slice(0, -13)\n : path\n return `postgresql://postgres:postgres@/postgres?host=${encodeURIComponent(socketDir)}`\n } else {\n // TCP connection\n return `postgresql://postgres:postgres@${host}:${port}/postgres`\n }\n }\n\n private async initializeDatabase(): Promise<void> {\n console.log(`Initializing PGLite with database: ${this.config.dbPath}`)\n console.log(`Debug level: ${this.config.debugLevel}`)\n\n this.db = new PGlite(this.config.dbPath, { debug: this.config.debugLevel })\n await this.db.waitReady\n console.log('PGlite database initialized')\n }\n\n private setupServerEventHandlers(): void {\n if (!this.server || !this.subprocessManager) {\n throw new Error('Server or subprocess manager not initialized')\n }\n\n this.server.addEventListener('listening', (event) => {\n const detail = (\n event as CustomEvent<{ port: number; host: string } | { host: string }>\n ).detail\n console.log(`PGLiteSocketServer listening on ${JSON.stringify(detail)}`)\n\n // Run the command after server starts listening\n if (this.config.runCommand && this.subprocessManager) {\n const databaseUrl = this.createDatabaseUrl()\n this.subprocessManager.spawn(\n this.config.runCommand,\n databaseUrl,\n this.config.includeDatabaseUrl,\n )\n }\n })\n\n this.server.addEventListener('connection', (event) => {\n const { clientAddress, clientPort } = (\n event as CustomEvent<{ clientAddress: string; clientPort: number }>\n ).detail\n console.log(`Client connected from ${clientAddress}:${clientPort}`)\n })\n\n this.server.addEventListener('error', (event) => {\n const error = (event as CustomEvent<Error>).detail\n console.error('Socket server error:', error)\n })\n }\n\n private setupSignalHandlers(): void {\n process.on('SIGINT', () => this.shutdown())\n process.on('SIGTERM', () => this.shutdown())\n }\n\n async start(): Promise<void> {\n try {\n // Initialize database\n await this.initializeDatabase()\n\n if (!this.db) {\n throw new Error('Database initialization failed')\n }\n\n // Create and setup the socket server\n this.server = new PGLiteSocketServer({\n db: this.db,\n port: this.config.port,\n host: this.config.host,\n path: this.config.path,\n inspect: this.config.debugLevel > 0,\n })\n\n // Create subprocess manager\n this.subprocessManager = new SubprocessManager((exitCode) => {\n this.shutdown(exitCode)\n })\n\n // Setup event handlers\n this.setupServerEventHandlers()\n this.setupSignalHandlers()\n\n // Start the server\n await this.server.start()\n } catch (error) {\n console.error('Failed to start PGLiteSocketServer:', error)\n throw error\n }\n }\n\n async shutdown(exitCode: number = 0): Promise<void> {\n console.log('\\nShutting down PGLiteSocketServer...')\n\n // Terminate subprocess if running\n if (this.subprocessManager) {\n this.subprocessManager.terminate(this.config.shutdownTimeout)\n }\n\n // Stop server\n if (this.server) {\n await this.server.stop()\n }\n\n // Close database\n if (this.db) {\n await this.db.close()\n }\n\n console.log('Server stopped')\n process.exit(exitCode)\n }\n}\n\nclass SubprocessManager {\n private childProcess: ChildProcess | null = null\n private onExit: (code: number) => void\n\n constructor(onExit: (code: number) => void) {\n this.onExit = onExit\n }\n\n get process(): ChildProcess | null {\n return this.childProcess\n }\n\n spawn(\n command: string,\n databaseUrl: string,\n includeDatabaseUrl: boolean,\n ): void {\n console.log(`Running command: ${command}`)\n\n // Prepare environment variables\n const env = { ...process.env }\n if (includeDatabaseUrl) {\n env.DATABASE_URL = databaseUrl\n console.log(`Setting DATABASE_URL=${databaseUrl}`)\n }\n\n // Parse and spawn the command\n const commandParts = command.trim().split(/\\s+/)\n this.childProcess = spawn(commandParts[0], commandParts.slice(1), {\n env,\n stdio: 'inherit',\n })\n\n this.childProcess.on('error', (error) => {\n console.error('Error running command:', error)\n // If subprocess fails to start, shutdown the server\n console.log('Subprocess failed to start, shutting down...')\n this.onExit(1)\n })\n\n this.childProcess.on('close', (code) => {\n console.log(`Command exited with code ${code}`)\n this.childProcess = null\n\n // If child process exits with non-zero code, notify parent\n if (code !== null && code !== 0) {\n console.log(\n `Child process failed with exit code ${code}, shutting down...`,\n )\n this.onExit(code)\n }\n })\n }\n\n terminate(timeout: number): void {\n if (this.childProcess) {\n console.log('Terminating child process...')\n this.childProcess.kill('SIGTERM')\n\n // Give it a moment to exit gracefully, then force kill if needed\n setTimeout(() => {\n if (this.childProcess && !this.childProcess.killed) {\n console.log('Force killing child process...')\n this.childProcess.kill('SIGKILL')\n }\n }, timeout)\n }\n }\n}\n\n// Main execution\nasync function main() {\n // Show help and exit if requested\n if (args.values.help) {\n console.log(help)\n process.exit(0)\n }\n\n try {\n const config = PGLiteServerRunner.parseConfig()\n const serverRunner = new PGLiteServerRunner(config)\n await serverRunner.start()\n } catch (error) {\n console.error('Unhandled error:', error)\n process.exit(1)\n }\n}\n\n// Run the main function\nmain()\n","import type { PGlite } from '@electric-sql/pglite'\nimport { createServer, Server, Socket } from 'net'\n\n// Connection queue timeout in milliseconds\nexport const CONNECTION_QUEUE_TIMEOUT = 60000 // 60 seconds\n\n/**\n * Options for creating a PGLiteSocketHandler\n */\nexport interface PGLiteSocketHandlerOptions {\n /** The PGlite database instance */\n db: PGlite\n /** Whether to close the socket when detached (default: false) */\n closeOnDetach?: boolean\n /** Print the incoming and outgoing data to the console in hex and ascii */\n inspect?: boolean\n /** Enable debug logging of method calls */\n debug?: boolean\n}\n\n/**\n * Low-level handler for a single socket connection to PGLite\n * Handles the raw protocol communication between a socket and PGLite\n */\nexport class PGLiteSocketHandler extends EventTarget {\n readonly db: PGlite\n private socket: Socket | null = null\n private active = false\n private closeOnDetach: boolean\n private resolveLock?: () => void\n private rejectLock?: (err: Error) => void\n private inspect: boolean\n private debug: boolean\n private readonly id: number\n\n // Static counter for generating unique handler IDs\n private static nextHandlerId = 1\n\n /**\n * Create a new PGLiteSocketHandler\n * @param options Options for the handler\n */\n constructor(options: PGLiteSocketHandlerOptions) {\n super()\n this.db = options.db\n this.closeOnDetach = options.closeOnDetach ?? false\n this.inspect = options.inspect ?? false\n this.debug = options.debug ?? false\n this.id = PGLiteSocketHandler.nextHandlerId++\n\n this.log('constructor: created new handler')\n }\n\n /**\n * Get the unique ID of this handler\n */\n public get handlerId(): number {\n return this.id\n }\n\n /**\n * Log a message if debug is enabled\n * @private\n */\n private log(message: string, ...args: any[]): void {\n if (this.debug) {\n console.log(`[PGLiteSocketHandler#${this.id}] ${message}`, ...args)\n }\n }\n\n /**\n * Attach a socket to this handler\n * @param socket The socket to attach\n * @returns this handler instance\n * @throws Error if a socket is already attached\n */\n public async attach(socket: Socket): Promise<PGLiteSocketHandler> {\n this.log(\n `attach: attaching socket from ${socket.remoteAddress}:${socket.remotePort}`,\n )\n\n if (this.socket) {\n throw new Error('Socket already attached')\n }\n\n this.socket = socket\n this.active = true\n\n // Ensure the PGlite instance is ready\n this.log(`attach: waiting for PGlite to be ready`)\n await this.db.waitReady\n\n // Hold the lock on the PGlite instance\n this.log(`attach: acquiring exclusive lock on PGlite instance`)\n await new Promise<void>((resolve) => {\n this.db.runExclusive(() => {\n // Ensure we have the lock on the PGlite instance\n resolve()\n\n // Use a promise to hold the lock on the PGlite instance\n // this can be resolved or rejected by the handler to release the lock\n return new Promise<void>((resolveLock, rejectLock) => {\n this.resolveLock = resolveLock\n this.rejectLock = rejectLock\n })\n })\n })\n\n // Setup event handlers\n this.log(`attach: setting up socket event handlers`)\n socket.on('data', async (data) => {\n try {\n const result = await this.handleData(data)\n this.log(`socket on data sent: ${result} bytes`)\n } catch (err) {\n this.log('socket on data error: ', err)\n }\n })\n socket.on('error', (err) => this.handleError(err))\n socket.on('close', () => this.handleClose())\n\n return this\n }\n\n /**\n * Detach the current socket from this handler\n * @param close Whether to close the socket when detaching (overrides constructor option)\n * @returns this handler instance\n */\n public detach(close?: boolean): PGLiteSocketHandler {\n this.log(`detach: detaching socket, close=${close ?? this.closeOnDetach}`)\n\n if (!this.socket) {\n this.log(`detach: no socket attached, nothing to do`)\n return this\n }\n\n // Remove all listeners\n this.socket.removeAllListeners('data')\n this.socket.removeAllListeners('error')\n this.socket.removeAllListeners('close')\n\n // Close the socket if requested\n if (close ?? this.closeOnDetach) {\n if (this.socket.writable) {\n this.log(`detach: closing socket`)\n this.socket.end()\n this.socket.destroy()\n }\n }\n\n // Release the lock on the PGlite instance\n this.log(`detach: releasing exclusive lock on PGlite instance`)\n this.resolveLock?.()\n\n this.socket = null\n this.active = false\n return this\n }\n\n /**\n * Check if a socket is currently attached\n */\n public get isAttached(): boolean {\n return this.socket !== null\n }\n\n /**\n * Handle incoming data from the socket\n */\n private async handleData(data: Buffer): Promise<number> {\n if (!this.socket || !this.active) {\n this.log(`handleData: no active socket, ignoring data`)\n return new Promise((_, reject) => reject(`no active socket`))\n }\n\n this.log(`handleData: received ${data.length} bytes`)\n\n // Print the incoming data to the console\n this.inspectData('incoming', data)\n\n try {\n // Process the raw protocol data\n this.log(`handleData: sending data to PGlite for processing`)\n const result = await this.db.execProtocolRaw(new Uint8Array(data))\n\n this.log(`handleData: received ${result.length} bytes from PGlite`)\n\n // Print the outgoing data to the console\n this.inspectData('outgoing', result)\n\n // Send the result back if the socket is still connected\n if (this.socket && this.socket.writable && this.active) {\n if (result.length <= 0) {\n this.log(`handleData: cowardly refusing to send empty packet`)\n return new Promise((_, reject) => reject('no data'))\n }\n\n const promise = new Promise<number>((resolve, reject) => {\n this.log(`handleData: writing response to socket`)\n if (this.socket) {\n this.socket.write(Buffer.from(result), (err?: Error) => {\n if (err) {\n reject(`Error while writing to the socket ${err.toString()}`)\n } else {\n resolve(result.length)\n }\n })\n } else {\n reject(`No socket`)\n }\n })\n\n // Emit data event with byte sizes\n this.dispatchEvent(\n new CustomEvent('data', {\n detail: { incoming: data.length, outgoing: result.length },\n }),\n )\n return promise\n } else {\n this.log(\n `handleData: socket no longer writable or active, discarding response`,\n )\n return new Promise((_, reject) =>\n reject(`No socket, not active or not writeable`),\n )\n }\n } catch (err) {\n this.log(`handleData: error processing data:`, err)\n this.handleError(err as Error)\n return new Promise((_, reject) =>\n reject(`Error while processing data ${(err as Error).toString()}`),\n )\n }\n }\n\n /**\n * Handle errors from the socket\n */\n private handleError(err: Error): void {\n this.log(`handleError:`, err)\n\n // Emit error event\n this.dispatchEvent(new CustomEvent('error', { detail: err }))\n\n // Reject the lock on the PGlite instance\n this.log(`handleError: rejecting exclusive lock on PGlite instance`)\n this.rejectLock?.(err)\n this.resolveLock = undefined\n this.rejectLock = undefined\n\n // Close the connection on error\n this.detach(true)\n }\n\n /**\n * Handle socket close event\n */\n private handleClose(): void {\n this.log(`handleClose: socket closed`)\n\n this.dispatchEvent(new CustomEvent('close'))\n this.detach(false) // Already closed, just clean up\n }\n\n /**\n * Print data in hex and ascii to the console\n */\n private inspectData(\n direction: 'incoming' | 'outgoing',\n data: Buffer | Uint8Array,\n ): void {\n if (!this.inspect) return\n console.log('-'.repeat(75))\n if (direction === 'incoming') {\n console.log('-> incoming', data.length, 'bytes')\n } else {\n console.log('<- outgoing', data.length, 'bytes')\n }\n\n // Process 16 bytes per line\n for (let offset = 0; offset < data.length; offset += 16) {\n // Calculate current chunk size (may be less than 16 for the last chunk)\n const chunkSize = Math.min(16, data.length - offset)\n\n // Build the hex representation\n let hexPart = ''\n for (let i = 0; i < 16; i++) {\n if (i < chunkSize) {\n const byte = data[offset + i]\n hexPart += byte.toString(16).padStart(2, '0') + ' '\n } else {\n hexPart += ' ' // 3 spaces for missing bytes\n }\n }\n\n // Build the ASCII representation\n let asciiPart = ''\n for (let i = 0; i < chunkSize; i++) {\n const byte = data[offset + i]\n // Use printable characters (32-126), replace others with a dot\n asciiPart += byte >= 32 && byte <= 126 ? String.fromCharCode(byte) : '.'\n }\n\n // Print the line with offset in hex, hex values, and ASCII representation\n console.log(\n `${offset.toString(16).padStart(8, '0')} ${hexPart} ${asciiPart}`,\n )\n }\n }\n}\n\n/**\n * Represents a queued connection with timeout\n */\ninterface QueuedConnection {\n socket: Socket\n clientInfo: {\n clientAddress: string\n clientPort: number\n }\n timeoutId: NodeJS.Timeout\n}\n\n/**\n * Options for creating a PGLiteSocketServer\n */\nexport interface PGLiteSocketServerOptions {\n /** The PGlite database instance */\n db: PGlite\n /** The port to listen on (default: 5432) */\n port?: number\n /** The host to bind to (default: 127.0.0.1) */\n host?: string\n /** Unix socket path to bind to (default: undefined). If specified, takes precedence over host:port */\n path?: string\n /** Print the incoming and outgoing data to the console in hex and ascii */\n inspect?: boolean\n /** Connection queue timeout in milliseconds (default: 10000) */\n connectionQueueTimeout?: number\n /** Enable debug logging of method calls */\n debug?: boolean\n}\n\n/**\n * High-level server that manages socket connections to PGLite\n * Creates and manages a TCP server and handles client connections\n */\nexport class PGLiteSocketServer extends EventTarget {\n readonly db: PGlite\n private server: Server | null = null\n private port?: number\n private host?: string\n private path?: string\n private active = false\n private inspect: boolean\n private debug: boolean\n private connectionQueueTimeout: number\n private activeHandler: PGLiteSocketHandler | null = null\n private connectionQueue: QueuedConnection[] = []\n private handlerCount: number = 0\n\n /**\n * Create a new PGLiteSocketServer\n * @param options Options for the server\n */\n constructor(options: PGLiteSocketServerOptions) {\n super()\n this.db = options.db\n if (options.path) {\n this.path = options.path\n } else {\n this.port = options.port || 5432\n this.host = options.host || '127.0.0.1'\n }\n this.inspect = options.inspect ?? false\n this.debug = options.debug ?? false\n this.connectionQueueTimeout =\n options.connectionQueueTimeout ?? CONNECTION_QUEUE_TIMEOUT\n\n this.log(`constructor: created server on ${this.host}:${this.port}`)\n this.log(\n `constructor: connection queue timeout: ${this.connectionQueueTimeout}ms`,\n )\n }\n\n /**\n * Log a message if debug is enabled\n * @private\n */\n private log(message: string, ...args: any[]): void {\n if (this.debug) {\n console.log(`[PGLiteSocketServer] ${message}`, ...args)\n }\n }\n\n /**\n * Start the socket server\n * @returns Promise that resolves when the server is listening\n */\n public async start(): Promise<void> {\n this.log(`start: starting server on ${this.getServerConn()}`)\n\n if (this.server) {\n throw new Error('Socket server already started')\n }\n\n this.active = true\n this.server = createServer((socket) => this.handleConnection(socket))\n\n return new Promise<void>((resolve, reject) => {\n if (!this.server) return reject(new Error('Server not initialized'))\n\n this.server.on('error', (err) => {\n this.log(`start: server error:`, err)\n this.dispatchEvent(new CustomEvent('error', { detail: err }))\n reject(err)\n })\n\n if (this.path) {\n this.server.listen(this.path, () => {\n this.log(`start: server listening on ${this.getServerConn()}`)\n this.dispatchEvent(\n new CustomEvent('listening', {\n detail: { path: this.path },\n }),\n )\n resolve()\n })\n } else {\n this.server.listen(this.port, this.host, () => {\n this.log(`start: server listening on ${this.getServerConn()}`)\n this.dispatchEvent(\n new CustomEvent('listening', {\n detail: { port: this.port, host: this.host },\n }),\n )\n resolve()\n })\n }\n })\n }\n\n public getServerConn(): string {\n if (this.path) return this.path\n return `${this.host}:${this.port}`\n }\n\n /**\n * Stop the socket server\n * @returns Promise that resolves when the server is closed\n */\n public async stop(): Promise<void> {\n this.log(`stop: stopping server`)\n\n this.active = false\n\n // Clear connection queue\n this.log(\n `stop: clearing connection queue (${this.connectionQueue.length} connections)`,\n )\n\n this.connectionQueue.forEach((queuedConn) => {\n clearTimeout(queuedConn.timeoutId)\n if (queuedConn.socket.writable) {\n this.log(\n `stop: closing queued connection from ${queuedConn.clientInfo.clientAddress}:${queuedConn.clientInfo.clientPort}`,\n )\n queuedConn.socket.end()\n }\n })\n this.connectionQueue = []\n\n // Detach active handler if exists\n if (this.activeHandler) {\n this.log(`stop: detaching active handler #${this.activeHandlerId}`)\n this.activeHandler.detach(true)\n this.activeHandler = null\n }\n\n if (!this.server) {\n this.log(`stop: server not running, nothing to do`)\n return Promise.resolve()\n }\n\n return new Promise<void>((resolve) => {\n if (!this.server) return resolve()\n\n this.server.close(() => {\n this.log(`stop: server closed`)\n this.server = null\n this.dispatchEvent(new CustomEvent('close'))\n resolve()\n })\n })\n }\n\n /**\n * Get the active handler ID, or null if no active handler\n */\n private get activeHandlerId(): number | null {\n return this.activeHandler?.handlerId ?? null\n }\n\n /**\n * Handle a new client connection\n */\n private async handleConnection(socket: Socket): Promise<void> {\n const clientInfo = {\n clientAddress: socket.remoteAddress || 'unknown',\n clientPort: socket.remotePort || 0,\n }\n\n this.log(\n `handleConnection: new connection from ${clientInfo.clientAddress}:${clientInfo.clientPort}`,\n )\n\n // If server is not active, close the connection immediately\n if (!this.active) {\n this.log(`handleConnection: server not active, closing connection`)\n socket.end()\n return\n }\n\n // If we don't have an active handler or it's not attached, we can use this connection immediately\n if (!this.activeHandler || !this.activeHandler.isAttached) {\n this.log(`handleConnection: no active handler, attaching socket directly`)\n this.dispatchEvent(new CustomEvent('connection', { detail: clientInfo }))\n await this.attachSocketToNewHandler(socket, clientInfo)\n return\n }\n\n // Otherwise, queue the connection\n this.log(\n `handleConnection: active handler #${this.activeHandlerId} exists, queueing connection`,\n )\n this.enqueueConnection(socket, clientInfo)\n }\n\n /**\n * Add a connection to the queue\n */\n private enqueueConnection(\n socket: Socket,\n clientInfo: { clientAddress: string; clientPort: number },\n ): void {\n this.log(\n `enqueueConnection: queueing connection from ${clientInfo.clientAddress}:${clientInfo.clientPort}, timeout: ${this.connectionQueueTimeout}ms`,\n )\n\n // Set a timeout for this queued connection\n const timeoutId = setTimeout(() => {\n this.log(\n `enqueueConnection: timeout for connection from ${clientInfo.clientAddress}:${clientInfo.clientPort}`,\n )\n\n // Remove from queue\n this.connectionQueue = this.connectionQueue.filter(\n (queuedConn) => queuedConn.socket !== socket,\n )\n\n // End the connection if it's still open\n if (socket.writable) {\n this.log(`enqueueConnection: closing timed out connection`)\n socket.end()\n }\n\n this.dispatchEvent(\n new CustomEvent('queueTimeout', {\n detail: { ...clientInfo, queueSize: this.connectionQueue.length },\n }),\n )\n }, this.connectionQueueTimeout)\n\n // Add to queue\n this.connectionQueue.push({ socket, clientInfo, timeoutId })\n\n this.log(\n `enqueueConnection: connection queued, queue size: ${this.connectionQueue.length}`,\n )\n\n this.dispatchEvent(\n new CustomEvent('queuedConnection', {\n detail: { ...clientInfo, queueSize: this.connectionQueue.length },\n }),\n )\n }\n\n /**\n * Process the next connection in the queue\n */\n private processNextInQueue(): void {\n this.log(\n `processNextInQueue: processing next connection, queue size: ${this.connectionQueue.length}`,\n )\n\n // No connections in queue or server not active\n if (this.connectionQueue.length === 0 || !this.active) {\n this.log(\n `processNextInQueue: no connections in queue or server not active, nothing to do`,\n )\n return\n }\n\n // Get the next connection\n const nextConn = this.connectionQueue.shift()\n if (!nextConn) return\n\n this.log(\n `processNextInQueue: processing connection from ${nextConn.clientInfo.clientAddress}:${nextConn.clientInfo.clientPort}`,\n )\n\n // Clear the timeout\n clearTimeout(nextConn.timeoutId)\n\n // Check if the socket is still valid\n if (!nextConn.socket.writable) {\n this.log(\n `processNextInQueue: socket no longer writable, skipping to next connection`,\n )\n // Socket closed while waiting, process next in queue\n this.processNextInQueue()\n return\n }\n\n // Attach this socket to a new handler\n this.attachSocketToNewHandler(nextConn.socket, nextConn.clientInfo).catch(\n (err) => {\n this.log(`processNextInQueue: error attaching socket:`, err)\n this.dispatchEvent(new CustomEvent('error', { detail: err }))\n // Try the next connection\n this.processNextInQueue()\n },\n )\n }\n\n /**\n * Attach a socket to a new handler\n */\n private async attachSocketToNewHandler(\n socket: Socket,\n clientInfo: { clientAddress: string; clientPort: number },\n ): Promise<void> {\n this.handlerCount++\n\n this.log(\n `attachSocketToNewHandler: creating new handler for ${clientInfo.clientAddress}:${clientInfo.clientPort} (handler #${this.handlerCount})`,\n )\n\n // Create a new handler for this connection\n const handler = new PGLiteSocketHandler({\n db: this.db,\n closeOnDetach: true,\n inspect: this.inspect,\n debug: this.debug,\n })\n\n // Forward error events from the handler\n handler.addEventListener('error', (event) => {\n this.log(\n `handler #${handler.handlerId}: error from handler:`,\n (event as CustomEvent<Error>).detail,\n )\n this.dispatchEvent(\n new CustomEvent('error', {\n detail: (event as CustomEvent<Error>).detail,\n }),\n )\n })\n\n // Handle close event to process next queued connection\n handler.addEventListener('close', () => {\n this.log(`handler #${handler.handlerId}: closed`)\n\n // If this is our active handler, clear it\n if (this.activeHandler === handler) {\n this.log(\n `handler #${handler.handlerId}: was active handler, processing next connection in queue`,\n )\n this.activeHandler = null\n // Process next connection in queue\n this.processNextInQueue()\n }\n })\n\n try {\n // Set as active handler\n this.activeHandler = handler\n\n this.log(`handler #${handler.handlerId}: attaching socket`)\n\n // Attach the socket to the handler\n await handler.attach(socket)\n\n this.dispatchEvent(new CustomEvent('connection', { detail: clientInfo }))\n } catch (err) {\n // If there was an error attaching, clean up\n this.log(`handler #${handler.handlerId}: error attaching socket:`, err)\n this.activeHandler = null\n if (socket.writable) {\n socket.end()\n }\n throw err\n }\n }\n}\n"],"mappings":"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","names":["import_pglite","import_net","CONNECTION_QUEUE_TIMEOUT","_PGLiteSocketHandler","options","message","args","socket","resolve","resolveLock","rejectLock","data","result","err","close","_","reject","promise","direction","offset","chunkSize","hexPart","i","byte","asciiPart","PGLiteSocketHandler","PGLiteSocketServer","queuedConn","clientInfo","timeoutId","nextConn","handler","event","import_node_util","import_node_child_process","args","help","PGLiteServerRunner","config","host","port","path","socketDir","event","detail","databaseUrl","clientAddress","clientPort","error","PGLiteSocketServer","SubprocessManager","exitCode","onExit","command","includeDatabaseUrl","env","commandParts","code","timeout","main"]}