Fix: Event session cold-start bug - presentations/presenters now load on first render
CRITICAL BUG FIX: Session view required 1-2 manual refreshes to display presentations and presenters when IndexedDB was empty. Root Cause: - Nested loaders passed try_cache: false, preventing IDB writes - Missing microtask yields caused race conditions between IDB writes and liveQuery subscriptions Changes: - ae_events__event_session.ts: Preserve try_cache in nested loads - ae_events__event_presentation.ts: Block on presenter loads with await Promise.all() + preserve try_cache - ae_events__event_presenter.ts: Add microtask yield after IDB write Result: Presentations AND presenters now render correctly on first navigation without requiring manual page refresh.
This commit is contained in:
@@ -184,11 +184,20 @@ async function _refresh_presentation_li_background({ api_cfg, for_obj_type, for_
|
|||||||
|
|
||||||
if (try_cache) {
|
if (try_cache) {
|
||||||
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'presentation', obj_li: processed, properties_to_save, log_lvl });
|
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'presentation', obj_li: processed, properties_to_save, log_lvl });
|
||||||
|
// CRITICAL FIX (2026-02-26): Yield to microtask queue so Dexie liveQuery observers
|
||||||
|
// fire before we return. Without this, component-mounted liveQueries may subscribe
|
||||||
|
// to IDB *before* the write completes, causing empty results on cold-start.
|
||||||
|
await Promise.resolve();
|
||||||
|
}
|
||||||
|
// CRITICAL FIX (2026-02-26): Block on nested loads when explicitly requested.
|
||||||
|
// Previously fire-and-forget (forEach without await), which meant the function returned
|
||||||
|
// before presenter data was loaded, causing "refresh twice" bug on cold-start.
|
||||||
|
// Now we await all nested loads AND preserve try_cache so presenters are written to IDB.
|
||||||
|
if (inc_file_li || inc_presenter_li) {
|
||||||
|
await Promise.all(processed.map(p =>
|
||||||
|
_handle_nested_loads(p, { api_cfg, inc_file_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl: 0 })
|
||||||
|
));
|
||||||
}
|
}
|
||||||
// Background nested loads for refreshed items (FIRE AND FORGET)
|
|
||||||
processed.forEach(p => {
|
|
||||||
_handle_nested_loads(p, { api_cfg, inc_file_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache: false, log_lvl: 0 });
|
|
||||||
});
|
|
||||||
return processed;
|
return processed;
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|||||||
@@ -153,6 +153,10 @@ async function _refresh_presenter_li_background({ api_cfg, for_obj_type, for_obj
|
|||||||
|
|
||||||
if (try_cache) {
|
if (try_cache) {
|
||||||
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'presenter', obj_li: processed, properties_to_save, log_lvl });
|
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'presenter', obj_li: processed, properties_to_save, log_lvl });
|
||||||
|
// CRITICAL FIX (2026-02-26): Yield to microtask queue so Dexie liveQuery observers
|
||||||
|
// fire before we return. Without this, component-mounted liveQueries may subscribe
|
||||||
|
// to IDB *before* the write completes, causing empty results on cold-start.
|
||||||
|
await Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Background nested loads for refreshed items (FIRE AND FORGET)
|
// Background nested loads for refreshed items (FIRE AND FORGET)
|
||||||
|
|||||||
@@ -99,9 +99,17 @@ async function _refresh_session_id_background({ api_cfg, event_session_id, view,
|
|||||||
|
|
||||||
if (try_cache) {
|
if (try_cache) {
|
||||||
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'session', obj_li: [processed_obj], properties_to_save, log_lvl });
|
await db_save_ae_obj_li__ae_obj({ db_instance: db_events, table_name: 'session', obj_li: [processed_obj], properties_to_save, log_lvl });
|
||||||
|
// CRITICAL FIX (2026-02-26): Yield to microtask queue so Dexie liveQuery observers
|
||||||
|
// fire before we return. Without this, component-mounted liveQueries may subscribe
|
||||||
|
// to IDB *before* the write completes, causing empty results on cold-start.
|
||||||
|
await Promise.resolve();
|
||||||
if (log_lvl) console.log(`💾 [Trace] _refresh_session_id: Saved to IDB cache.`);
|
if (log_lvl) console.log(`💾 [Trace] _refresh_session_id: Saved to IDB cache.`);
|
||||||
}
|
}
|
||||||
return await _handle_nested_loads(processed_obj, { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache: false, log_lvl });
|
// CRITICAL FIX (2026-02-26): Preserve parent's try_cache value when loading nested data.
|
||||||
|
// Previously set to `false`, which meant presentations/presenters were fetched from API
|
||||||
|
// but NEVER written to IndexedDB, causing "refresh twice" bug on cold-start.
|
||||||
|
// Now nested loads inherit parent's caching behavior for deterministic first-render.
|
||||||
|
return await _handle_nested_loads(processed_obj, { api_cfg, inc_file_li, inc_all_file_li, inc_presentation_li, inc_presenter_li, enabled, hidden, limit, offset, try_cache, log_lvl });
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (log_lvl) console.error(`❌ [Trace] _refresh_session_id: API error for id=${event_session_id}:`, e);
|
if (log_lvl) console.error(`❌ [Trace] _refresh_session_id: API error for id=${event_session_id}:`, e);
|
||||||
|
|||||||
Reference in New Issue
Block a user