fix: injectable tunnel log label, honest truncate budget comment
This commit is contained in:
1 parent
6a2706130a
commit
703df24b13
4 files changed
+42
-6
No files matched your search
@@ -32,7 +32,10 @@ export const sliceUtf8 = (s: string, maxBytes: number): string => {
|
||||
}
|
||||
|
||||
// Serialize `value` to JSON and, if it exceeds `maxBytes` (UTF-8), return a
|
||||
// truncated marker object whose own serialization stays within `maxBytes`.
|
||||
// truncated marker object. A fixed 256-byte margin is reserved for the marker
|
||||
// metadata, so the marker's own serialization stays within `maxBytes` for any
|
||||
// budget at or above a few hundred bytes (esmole uses 100 KB). For
|
||||
// pathologically tiny budgets the marker may exceed `maxBytes`.
|
||||
export const truncateJsonBudget = (
|
||||
value: unknown,
|
||||
maxBytes: number
|
||||
|
||||
@@ -50,7 +50,8 @@ export const buildSshAuth = (
|
||||
export const openTunnel = async (
|
||||
ssh: SshConfig,
|
||||
dstHost: string,
|
||||
dstPort: number
|
||||
dstPort: number,
|
||||
logLabel: string = 'ssh-tunnel'
|
||||
): Promise<Tunnel> => {
|
||||
const client = new Client()
|
||||
|
||||
@@ -67,7 +68,7 @@ export const openTunnel = async (
|
||||
|
||||
// After 'ready' resolved, later ssh errors must not crash the process.
|
||||
client.on('error', (error) => {
|
||||
console.error('ssh-tunnel: ssh tunnel error: ' + error.message)
|
||||
console.error(logLabel + ': ssh tunnel error: ' + error.message)
|
||||
})
|
||||
|
||||
let closed = false
|
||||
@@ -140,7 +141,7 @@ export const openTunnel = async (
|
||||
// without a persistent one, a later listener error is swallowed and the
|
||||
// tunnel silently serves a dead socket. Mark it closed instead.
|
||||
server.on('error', (error) => {
|
||||
console.error('ssh-tunnel: tunnel listener error: ' + error.message)
|
||||
console.error(logLabel + ': tunnel listener error: ' + error.message)
|
||||
markClosed()
|
||||
})
|
||||
|
||||
|
||||
@@ -248,11 +248,34 @@ describe('openTunnel', () => {
|
||||
created.push(server)
|
||||
return server
|
||||
})
|
||||
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const tunnel = await openTunnel(sshConfig({ password: 'pw' }), 'db-host', 5432)
|
||||
// A listener error after listen() resolved must not be swallowed: it
|
||||
// marks the tunnel closed so the manager can rebuild it.
|
||||
created[0].emit('error', new Error('EADDRNOTAVAIL'))
|
||||
expect(tunnel.isClosed()).toBe(true)
|
||||
// Default log label brands the diagnostic with 'ssh-tunnel:'.
|
||||
expect(errSpy).toHaveBeenCalledWith('ssh-tunnel: tunnel listener error: EADDRNOTAVAIL')
|
||||
errSpy.mockRestore()
|
||||
spy.mockRestore()
|
||||
await tunnel.close()
|
||||
})
|
||||
|
||||
it('uses a custom logLabel prefix on diagnostics', async () => {
|
||||
const created: net.Server[] = []
|
||||
const realCreateServer = net.createServer.bind(net)
|
||||
const spy = vi.spyOn(net, 'createServer').mockImplementation((handler) => {
|
||||
const server = realCreateServer(handler as (socket: net.Socket) => void)
|
||||
created.push(server)
|
||||
return server
|
||||
})
|
||||
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
|
||||
const tunnel = await openTunnel(sshConfig({ password: 'pw' }), 'db-host', 5432, 'dbmole')
|
||||
created[0].emit('error', new Error('EADDRNOTAVAIL'))
|
||||
expect(tunnel.isClosed()).toBe(true)
|
||||
// The injected label replaces the default prefix token.
|
||||
expect(errSpy).toHaveBeenCalledWith('dbmole: tunnel listener error: EADDRNOTAVAIL')
|
||||
errSpy.mockRestore()
|
||||
spy.mockRestore()
|
||||
await tunnel.close()
|
||||
})
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { createManager as coreCreate, type ManagedConnection, type Manager } from '@dbmole/core'
|
||||
import {
|
||||
createManager as coreCreate,
|
||||
type ManagedConnection,
|
||||
type Manager,
|
||||
openTunnel
|
||||
} from '@dbmole/core'
|
||||
import type { DbRegistry } from '../config/registry.js'
|
||||
import type { ConnectionConfig } from '../schema.js'
|
||||
import { createBackend, resolvePort } from '../sqlBackend.js'
|
||||
@@ -8,4 +13,8 @@ export type DbManager = Manager<ConnectionConfig, Driver>
|
||||
export type DbManaged = ManagedConnection<ConnectionConfig, Driver>
|
||||
|
||||
export const createManager = (registry: DbRegistry): DbManager =>
|
||||
coreCreate<ConnectionConfig, Driver>(registry, { createBackend, resolvePort })
|
||||
coreCreate<ConnectionConfig, Driver>(registry, {
|
||||
createBackend,
|
||||
resolvePort,
|
||||
createTunnel: (ssh, host, port) => openTunnel(ssh, host, port, 'dbmole')
|
||||
})
|
||||
Reference in new issue
Block a user