Browse Source

*Goal*

Make file caching fire-and-forget so IndexedDB writes do not block parsing and video loading.

*Actions*

Update the file pipeline code where saveFileWithMetadata(...) is called:

Replace await saveFileWithMetadata(...) with a non-blocking call that stores the promise in an array, e.g. cachePromises.push(saveFileWithMetadata(...).catch(e => logWarning(e))).

At the end of the pipeline kick off Promise.allSettled(cachePromises) but do not await it before parsing starts; instead log results or show a non-blocking notification on failure.

Add a configurable CACHE_BLOCKING boolean flag in config. Default false; if true (special mode) allow blocking for debugging.

Add logging and UI notification for cache failures without blocking the pipeline. Convert any alert() on quota errors into a non-blocking modal message or toast.

Add unit tests / smoke tests:

Simulate slow saveFileWithMetadata() (wrap with artificial delay) and confirm parsing and video loading start immediately without waiting for caching to finish.

Simulate a QuotaExceededError and confirm the pipeline continues.

*Check list*

 Replace await saveFileWithMetadata(...) with non-blocking logic.

 Pipeline starts parsing immediately even when cache save is delayed.

 Promise.allSettled(cachePromises) is triggered and results logged.

 UI shows non-blocking notification for cache failures (no alert() popups).

 Tests simulate slow save and quota errors and pass.
refactor/sync-centralize
RUSHIL AMBARISH KADU 6 months ago
parent
commit
59fef58ab4
  1. 6
      steps/package-lock.json
  2. 3
      steps/src/db.js
  3. 28
      steps/src/fileLoader.js

6
steps/package-lock.json

@ -0,0 +1,6 @@
{
"name": "steps",
"lockfileVersion": 3,
"requires": true,
"packages": {}
}

3
steps/src/db.js

@ -1,6 +1,7 @@
let db;
let dbReadyPromise;
let dbReadyResolve;
import { showModal } from "./modal.js";
// Initialize the promise that tracks DB readiness
dbReadyPromise = new Promise((resolve) => {
@ -72,7 +73,7 @@ export function saveFileWithMetadata(key, file) {
// Gracefully handle errors, especially quota limits
transaction.onerror = (event) => {
if (event.target.error.name === 'QuotaExceededError') {
alert("Could not cache file: Browser storage quota exceeded. The app will still work for this session.");
showModal("Could not cache file: Browser storage quota exceeded. The app will still work for this session, but files won't be saved for next time.");
resolve(); // Resolve anyway to let the app continue without caching
} else {
console.error(`Error saving file '${key}':`, event.target.error);

28
steps/src/fileLoader.js

@ -1,4 +1,5 @@
import { appState } from "./state.js";
import { debugFlags } from "./debug.js";
import { saveFileWithMetadata } from "./db.js";
import { parseVisualizationJson } from "./fileParsers.js";
import {
@ -60,17 +61,33 @@ async function processFilePipeline(jsonFile, videoFile, fromCache) {
// 1. Show the unified loading modal.
showLoadingModal("Processing files...");
const cachePromises = [];
// --- PART A: Setup Filenames & Cache (Moved Up) ---
if (jsonFile) {
appState.jsonFilename = jsonFile.name;
localStorage.setItem("jsonFilename", appState.jsonFilename);
if (!fromCache) await saveFileWithMetadata("json", jsonFile);
if (!fromCache) {
const savePromise = saveFileWithMetadata("json", jsonFile).catch((e) =>
console.warn(`Non-blocking cache save failed for JSON:`, e)
);
if (debugFlags.CACHE_BLOCKING) {
await savePromise;
} else {
cachePromises.push(savePromise);
}
}
}
if (videoFile) {
appState.videoFilename = videoFile.name;
localStorage.setItem("videoFilename", appState.videoFilename);
if (!fromCache) await saveFileWithMetadata("video", videoFile);
if (!fromCache) {
const savePromise = saveFileWithMetadata("video", videoFile).catch((e) =>
console.warn(`Non-blocking cache save failed for Video:`, e)
);
cachePromises.push(savePromise);
}
}
// --- PART B: Calculate Offset (Moved Up) ---
@ -137,6 +154,13 @@ async function processFilePipeline(jsonFile, videoFile, fromCache) {
// Hide modal
updateLoadingModal(100, "Complete!");
setTimeout(hideModal, 300);
// Log the results of the non-blocking cache operations once they complete.
if (cachePromises.length > 0) {
Promise.allSettled(cachePromises).then((results) => {
console.log("Non-blocking cache operations finished:", results);
});
}
}

Loading…
Cancel
Save