seguimos confiando en codex
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 1m4s

This commit is contained in:
2025-11-22 00:57:13 -06:00
parent 9b1628485f
commit 47c42cbcf3
3 changed files with 52 additions and 26 deletions

View File

@@ -49,25 +49,25 @@
label: 'No hay lotes registrados' label: 'No hay lotes registrados'
}" }"
> >
<template #codigo-cell="{ row }"> <template #codigo-cell="{ getValue }">
<span class="font-mono font-semibold">{{ row.codigo || '-' }}</span> <span class="font-mono font-semibold">{{ getValue() || '-' }}</span>
</template> </template>
<template #tipo-cell="{ row }"> <template #tipo-cell="{ getValue }">
<UBadge :color="getTipoColor(row.tipo)" variant="subtle"> <UBadge :color="getTipoColor(getValue())" variant="subtle">
{{ getTipoLabel(row.tipo) }} {{ getTipoLabel(getValue()) }}
</UBadge> </UBadge>
</template> </template>
<template #cantidad_kg-cell="{ row }"> <template #cantidad_kg-cell="{ getValue }">
<span v-if="row.cantidad_kg" class="font-medium"> <span v-if="getValue()" class="font-medium">
{{ row.cantidad_kg.toLocaleString('es-AR') }} kg {{ getValue().toLocaleString('es-AR') }} kg
</span> </span>
<span v-else class="text-gray-400">-</span> <span v-else class="text-gray-400">-</span>
</template> </template>
<template #fecha_creado-cell="{ row }"> <template #fecha_creado-cell="{ getValue }">
{{ formatDate(row.fecha_creado) }} {{ formatDate(getValue()) }}
</template> </template>
<template #actions-cell="{ row }"> <template #actions-cell="{ row }">

View File

@@ -49,17 +49,17 @@
label: 'No hay operaciones registradas' label: 'No hay operaciones registradas'
}" }"
> >
<template #tipo-cell="{ row }"> <template #tipo-cell="{ row, getValue }">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<UIcon :name="getTipoIcon(row.tipo)" class="w-4 h-4" /> <UIcon :name="getTipoIcon(getValue())" class="w-4 h-4" />
<UBadge :color="getTipoColor(row.tipo)" variant="subtle"> <UBadge :color="getTipoColor(getValue())" variant="subtle">
{{ getTipoLabel(row.tipo) }} {{ getTipoLabel(getValue()) }}
</UBadge> </UBadge>
</div> </div>
</template> </template>
<template #fecha-cell="{ row }"> <template #fecha-cell="{ getValue }">
{{ formatDate(row.fecha) }} {{ formatDate(getValue()) }}
</template> </template>
<template #actions-cell="{ row }"> <template #actions-cell="{ row }">

View File

@@ -4,6 +4,7 @@ import { useRuntimeConfig } from '#imports'
const { Pool } = pg const { Pool } = pg
let pool: pg.Pool | null = null let pool: pg.Pool | null = null
let connectionStringLogged = false
function buildConnectionString(): string { function buildConnectionString(): string {
const config = useRuntimeConfig() const config = useRuntimeConfig()
@@ -28,6 +29,12 @@ export function getPool(): pg.Pool {
if (!pool) { if (!pool) {
const connectionString = buildConnectionString() const connectionString = buildConnectionString()
if (!connectionStringLogged && process.env.NODE_ENV !== 'production') {
const masked = connectionString.replace(/:\/\/([^:]+):([^@]+)@/, '://$1:*****@')
console.log('[db] Usando connectionString:', masked)
connectionStringLogged = true
}
pool = new Pool({ pool = new Pool({
connectionString, connectionString,
max: 10, max: 10,
@@ -58,7 +65,9 @@ export async function query<T = any>(
): Promise<pg.QueryResult<T>> { ): Promise<pg.QueryResult<T>> {
const pool = getPool() const pool = getPool()
const start = Date.now() const start = Date.now()
const maxRetries = 2
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try { try {
const result = await pool.query<T>(text, params) const result = await pool.query<T>(text, params)
const duration = Date.now() - start const duration = Date.now() - start
@@ -68,11 +77,28 @@ export async function query<T = any>(
} }
return result return result
} catch (error) { } catch (error: any) {
console.error('Error ejecutando query:', { text, params, error }) const isAuthError = error?.code === '28P01'
const isConnError = ['ECONNREFUSED', 'ECONNRESET', '57P01'].includes(error?.code)
const shouldRetry = attempt < maxRetries && (isAuthError || isConnError)
console.error('Error ejecutando query:', { text, params, error: error?.message, code: error?.code, attempt })
if (shouldRetry) {
// Pequeño backoff y reintento
await new Promise((res) => setTimeout(res, 500 * (attempt + 1)))
// Resetear pool en auth/conn error por si la contraseña/estado cambia en caliente
try {
await pool.end()
} catch (_) {}
pool = null
continue
}
throw error throw error
} }
} }
}
/** /**
* Obtiene un cliente del pool para ejecutar transacciones. * Obtiene un cliente del pool para ejecutar transacciones.