/**
 * DbPort — re-export of the existing minimal DbClient shape from
 * tracking/agent-run-tracker. Alias DbPort is the port-suffixed name
 * used across other ports; DbClient remains exported for back-compat.
 *
 * OTel instrumentation: import { createTracedDbPort } to wrap any
 * DbPort implementation with OpenTelemetry spans per query.
 * Gracefully degrades to noop spans when no OTel SDK is installed.
 */
import { SpanStatusCode, trace } from "@opentelemetry/api";
const PORT_TRACER = trace.getTracer("vauban-agent-sdk.ports", "0.1.0");
// ─── Typed errors ─────────────────────────────────────────────────────────────
/**
 * Thrown when the database connection is lost (ECONNREFUSED, pool exhausted,
 * or TLS handshake failed). Callers should retry with exponential backoff
 * once the connection pool is re-established.
 */
export class DbConnectionLostError extends Error {
    cause;
    constructor(message, cause) {
        super(message);
        this.cause = cause;
        this.name = "DbConnectionLostError";
        Object.setPrototypeOf(this, new.target.prototype);
    }
}
/**
 * Thrown when a database query exceeds the configured statement_timeout or
 * the caller-supplied timeoutMs. The query may have been cancelled by the
 * server — retrying the same query without changes is unlikely to succeed.
 */
export class DbQueryTimeoutError extends Error {
    cause;
    /** The SQL statement that timed out (truncated for logging). */
    queryPreview;
    /** Timeout that was exceeded, in milliseconds. */
    timeoutMs;
    constructor(message, queryPreview, timeoutMs, cause) {
        super(message);
        this.cause = cause;
        this.name = "DbQueryTimeoutError";
        this.queryPreview = queryPreview;
        this.timeoutMs = timeoutMs;
        Object.setPrototypeOf(this, new.target.prototype);
    }
}
/**
 * Wrap any DbPort implementation with OTel spans per query() call.
 * The span captures the SQL preview (first 200 chars) and params count.
 * Gracefully degrades to noop spans when no OTel SDK is installed.
 *
 * Usage:
 *   const raw: DbPort = pgPool;
 *   const traced = createTracedDbPort(raw);
 *   const { rows } = await traced.query("SELECT ...") // emits "db.query" span
 */
export function createTracedDbPort(impl) {
    return {
        async query(sql, params) {
            return PORT_TRACER.startActiveSpan("db.query", {
                attributes: {
                    "db.sql_preview": sql.slice(0, 200),
                    "db.params_count": params?.length ?? 0,
                    "vauban.port.name": "db",
                },
            }, async (span) => {
                try {
                    const result = await impl.query(sql, params);
                    span.setAttributes({
                        "db.row_count": result.rowCount ?? result.rows.length,
                    });
                    span.setStatus({ code: SpanStatusCode.OK });
                    return result;
                }
                catch (err) {
                    const message = err instanceof Error ? err.message : String(err);
                    span.setStatus({ code: SpanStatusCode.ERROR, message });
                    if (err instanceof Error)
                        span.recordException(err);
                    throw err;
                }
                finally {
                    span.end();
                }
            });
        },
    };
}
//# sourceMappingURL=db.js.map