Skip to content

Commit cab4ce6

Browse files
authored
Allow OS to assign port automatically (#750)
* Allow OS to assign port automatically * PR feedback * formating * Add port 0 usage documentation to README
1 parent 16575de commit cab4ce6

File tree

3 files changed

+48
-4
lines changed

3 files changed

+48
-4
lines changed

packages/pglite-socket/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Creates a TCP server that allows PostgreSQL clients to connect to a PGlite datab
5858
#### Options
5959

6060
- `db: PGlite` - The PGlite database instance
61-
- `port?: number` - The port to listen on (default: 5432)
61+
- `port?: number` - The port to listen on (default: 5432). Use port 0 to let the OS assign an available port
6262
- `host?: string` - The host to bind to (default: 127.0.0.1)
6363
- `path?: string` - Unix socket path to bind to (takes precedence over host:port)
6464
- `inspect?: boolean` - Print the incoming and outgoing data to the console (default: false)
@@ -156,7 +156,7 @@ pglite-server --help
156156
### CLI Options
157157

158158
- `-d, --db=PATH` - Database path (default: memory://)
159-
- `-p, --port=PORT` - Port to listen on (default: 5432)
159+
- `-p, --port=PORT` - Port to listen on (default: 5432). Use 0 to let the OS assign an available port
160160
- `-h, --host=HOST` - Host to bind to (default: 127.0.0.1)
161161
- `-u, --path=UNIX` - Unix socket to bind to (takes precedence over host:port)
162162
- `-v, --debug=LEVEL` - Debug level 0-5 (default: 0)

packages/pglite-socket/src/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,12 @@ export class PGLiteSocketServer extends EventTarget {
371371
if (options.path) {
372372
this.path = options.path
373373
} else {
374-
this.port = options.port || 5432
374+
if (typeof options.port === 'number') {
375+
// Keep port undefined on port 0, will be set by the OS when we start the server.
376+
this.port = options.port ?? options.port
377+
} else {
378+
this.port = 5432
379+
}
375380
this.host = options.host || '127.0.0.1'
376381
}
377382
this.inspect = options.inspect ?? false
@@ -429,7 +434,15 @@ export class PGLiteSocketServer extends EventTarget {
429434
resolve()
430435
})
431436
} else {
432-
this.server.listen(this.port, this.host, () => {
437+
const server = this.server
438+
server.listen(this.port, this.host, () => {
439+
const address = server.address()
440+
// We are not using pipes, so return type should be AddressInfo
441+
if (address === null || typeof address !== 'object') {
442+
throw Error('Expected address info')
443+
}
444+
// Assign the new port number
445+
this.port = address.port
433446
this.log(`start: server listening on ${this.getServerConn()}`)
434447
this.dispatchEvent(
435448
new CustomEvent('listening', {

packages/pglite-socket/tests/index.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,37 @@ testSocket(async (connOptions) => {
476476
// Queue should be emptied
477477
expect((server as any).connectionQueue).toHaveLength(0)
478478
})
479+
480+
it('should start server with OS-assigned port when port is 0', async () => {
481+
server = new PGLiteSocketServer({
482+
db,
483+
host: connOptions.host,
484+
port: 0, // Let OS assign port
485+
})
486+
487+
await server.start()
488+
const assignedPort = (server as any).port
489+
expect(assignedPort).toBeGreaterThan(1024)
490+
491+
// Try to connect to confirm server is running
492+
const client = createConnection({
493+
port: assignedPort,
494+
host: connOptions.host,
495+
})
496+
497+
await new Promise<void>((resolve, reject) => {
498+
client.on('error', () => {
499+
reject(new Error('Connection should have failed'))
500+
})
501+
client.on('connect', () => {
502+
client.end()
503+
resolve()
504+
})
505+
setTimeout(resolve, 100)
506+
})
507+
508+
await server.stop()
509+
})
479510
})
480511
})
481512
})

0 commit comments

Comments
 (0)