Fix: solucionar error SQLITE_BUSY y mejorar backend

- Migrar de sqlite3 a better-sqlite3 con conexión persistente
- Configurar WAL mode, busy_timeout y PRAGMAs optimizados
- Implementar transacciones para operaciones bulk
- Corregir error initialLoadComplete en useHospitalStore.ts
- Agregar tablas usuarios y kv faltantes
- Actualizar .gitignore para archivos WAL de SQLite
This commit is contained in:
2026-04-24 02:06:21 -03:00
parent d30dbab8f0
commit e887d66411
8 changed files with 405 additions and 327 deletions
+53 -25
View File
@@ -111,33 +111,61 @@ export function useHospitalStore() {
return () => { mounted = false; };
}, []);
// Persist state to backend when it changes (debounced)
const [initialLoadComplete, setInitialLoadComplete] = useState(false);
// Persistence: event-driven + periodic save
const [saveQueue, setSaveQueue] = useState<string[]>([]);
const [isSaving, setIsSaving] = useState(false);
useEffect(() => {
if (isLoaded && !initialLoadComplete) {
setInitialLoadComplete(true);
}
}, [isLoaded, initialLoadComplete]);
useEffect(() => {
if (!initialLoadComplete) return;
const t = setTimeout(() => {
(async () => {
try {
const { currentUser, isAuthenticated, ...stateToSave } = state;
await fetch(`${API_BASE}/state`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(stateToSave),
});
} catch (err) {
// ignore save errors for now
// Track which parts changed
const [changedKeys, setChangedKeys] = useState<Set<string>>(new Set());
// Mark parts as changed
const markChanged = (key: string) => {
setChangedKeys(prev => {
const next = new Set(prev);
next.add(key);
return next;
});
};
// Save only changed parts
const saveChanges = useCallback(async () => {
if (isSaving || changedKeys.size === 0) return;
setIsSaving(true);
try {
const keysToSave = Array.from(changedKeys);
const partialState: any = {};
keysToSave.forEach(key => {
if (key in state) {
partialState[key] = state[key];
}
})();
}, 300);
return () => clearTimeout(t);
}, [state, initialLoadComplete]);
});
await fetch(`${API_BASE}/state/partial`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(partialState),
});
setChangedKeys(new Set());
} catch (err) {
console.error('Save error:', err);
} finally {
setIsSaving(false);
}
}, [state, changedKeys, isSaving]);
// Periodic save every 5 seconds if there are changes
useEffect(() => {
if (!isLoaded) return;
const t = setInterval(() => {
saveChanges();
}, 5000);
return () => clearInterval(t);
}, [isLoaded, saveChanges]);
// Also save on特定 events (optional)
const queueSave = (keys: string[]) => {
keys.forEach(markChanged);
};
// Utility functions
const getCamaAreaId = useCallback((camaId: string): string | null => {