Etapa 7B completa con Fix 4 agregado:
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Fix 4 Parte A: .maybeSingle() ya estaba aplicado (lo hiciste vos/el linter). Encontré y arreglé un bug adicional: con data === null (sin simulaciones), el código llamaba fromRow(null) y explotaba al leer row.id. Ahora getLatestByProcess retorna undefined limpiamente cuando no hay filas. Fix 4 Parte B: revisé ProcessCardWithSim en LibraryPage.tsx — ya tiene guard de cancelación y dependencias estables (process.id + acción de Zustand, que es una referencia fija). No encontré un loop real; lo más probable es que "~6 queries" correspondan a 6 procesos distintos disparando una query cada uno (correcto), posiblemente duplicado visualmente en dev por StrictMode (inocuo, no pasa en producción). Fixes 1, 2, 3 ya estaban implementados de antes y siguen verdes. Falta tu validación visual — en particular confirmar que el network tab ya no muestra 406 en simulations.
This commit is contained in:
@@ -133,14 +133,56 @@ async signInWithGoogle(): Promise<void> {
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
## Fix 4 — simulations: 406 por `.single()` sin filas + re-fetch en loop
|
||||||
|
|
||||||
|
### Problema
|
||||||
|
|
||||||
|
En el network tab se observan múltiples requests con 406 Not Acceptable:
|
||||||
|
```
|
||||||
|
GET simulations?select=*&process_id=eq.{id}&order=executed_at.desc&limit=1 → 406
|
||||||
|
```
|
||||||
|
|
||||||
|
**Causa:** supabase-js v2 `.single()` envía `Accept: application/vnd.pgrst.object+json`, que exige exactamente 1 fila. Si el proceso no tiene simulaciones aún (0 filas), PostgREST responde 406. El mismo query aparece ~6 veces para los mismos `processId` — señal de un `useEffect` re-fetching por dependencia incorrecta.
|
||||||
|
|
||||||
|
### Solución
|
||||||
|
|
||||||
|
**Parte A — Fix del 406:** en `src/persistence/supabase/simulation-repo.ts`, en el método que busca la última simulación por proceso, cambiar `.single()` por `.maybeSingle()`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Antes:
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('simulations')
|
||||||
|
.select('*')
|
||||||
|
.eq('process_id', processId)
|
||||||
|
.order('executed_at', { ascending: false })
|
||||||
|
.limit(1)
|
||||||
|
.single() // ← lanza 406 cuando no hay filas
|
||||||
|
|
||||||
|
// Después:
|
||||||
|
const { data, error } = await supabase
|
||||||
|
.from('simulations')
|
||||||
|
.select('*')
|
||||||
|
.eq('process_id', processId)
|
||||||
|
.order('executed_at', { ascending: false })
|
||||||
|
.limit(1)
|
||||||
|
.maybeSingle() // ← retorna null sin error cuando no hay filas
|
||||||
|
```
|
||||||
|
|
||||||
|
El caller debe manejar `data === null` como "sin simulación" (no como error).
|
||||||
|
|
||||||
|
**Parte B — Fix del re-fetch en loop:** localizar el `useEffect` que dispara esta query (probablemente en `LibraryPage.tsx` o en un hook de simulación). Revisar que sus dependencias no incluyan un objeto o array que se re-crea en cada render (patrón clásico de loop infinito). Si el array de dependencias contiene `processes` (que es un array nuevo en cada render del store), estabilizarlo con `useMemo` o extraer solo los IDs que realmente cambian.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## Orden de ejecución
|
## Orden de ejecución
|
||||||
|
|
||||||
1. Fix 3 — `SupabaseAuthService.signInWithGoogle()` (1 línea, más fácil de verificar primero)
|
1. Fix 3 — `SupabaseAuthService.signInWithGoogle()` (1 línea)
|
||||||
2. Fix 2 — función `formatCostPerHour` con precisión dinámica + aplicar en todos los contextos
|
2. Fix 4 — `.maybeSingle()` en simulation-repo + revisar re-fetch loop
|
||||||
3. Fix 1 — query param en ResourcesPanel + banner + botón en ResourceCatalogPage
|
3. Fix 2 — función `formatCostPerHour` con precisión dinámica + aplicar en todos los contextos
|
||||||
4. `npm run build` — debe pasar sin errores TypeScript
|
4. Fix 1 — query param en ResourcesPanel + banner + botón en ResourceCatalogPage
|
||||||
5. `npm run test` — debe mantener 521+ tests verdes
|
5. `npm run build` — debe pasar sin errores TypeScript
|
||||||
6. Commit: `fix(sprint-4/etapa-7b): selector cuenta Google + redondeo costo/hora + contexto catálogo`
|
6. `npm run test` — debe mantener 521+ tests verdes
|
||||||
|
7. Commit: `fix(sprint-4/etapa-7b): selector cuenta Google + redondeo costo/hora + contexto catálogo + simulations maybeSingle`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -153,6 +195,8 @@ async signInWithGoogle(): Promise<void> {
|
|||||||
- [ ] Botón "← Usar en proceso" aparece en cada fila cuando hay contexto de proceso
|
- [ ] Botón "← Usar en proceso" aparece en cada fila cuando hay contexto de proceso
|
||||||
- [ ] Click en "← Usar en proceso" navega a `/workspace/:processId`
|
- [ ] Click en "← Usar en proceso" navega a `/workspace/:processId`
|
||||||
- [ ] Navegar a `/recursos` directamente (sin `fromProcess`) no muestra banner ni botón extra
|
- [ ] Navegar a `/recursos` directamente (sin `fromProcess`) no muestra banner ni botón extra
|
||||||
|
- [ ] Network tab sin 406 en requests de `simulations`
|
||||||
|
- [ ] Network tab: el query de simulaciones no se repite en loop para el mismo `processId`
|
||||||
- [ ] Build limpio sin errores TypeScript
|
- [ ] Build limpio sin errores TypeScript
|
||||||
- [ ] 521+ tests verdes
|
- [ ] 521+ tests verdes
|
||||||
- [ ] **Validación visual del director** antes del OK formal
|
- [ ] **Validación visual del director** antes del OK formal
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ export const supabaseSimulationRepo = {
|
|||||||
.eq('process_id', processId)
|
.eq('process_id', processId)
|
||||||
.order('executed_at', { ascending: false })
|
.order('executed_at', { ascending: false })
|
||||||
.limit(1)
|
.limit(1)
|
||||||
.single()
|
.maybeSingle()
|
||||||
if (error) return undefined
|
if (error || !data) return undefined
|
||||||
return fromRow(data as Record<string, unknown>)
|
return fromRow(data as Record<string, unknown>)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user