fix(launcher): refresh file lists periodically to prune deleted/hidden files

The Launcher's background sync never called load_ae_obj_li__event_file for
presenter/session files. That function contains stale-record pruning that
removes deleted or hidden files from Dexie; without it, the Launcher's IDB
retained stale file records indefinitely until manually cleared.

Changes:
- refresh_presenter_data: add inc_file_li=true so presenter files are pruned
  every 120s via the existing presenter loop
- refresh_current_session_files(): new function that fetches/prunes session-
  level file lists for the selected session
- timer__file_list: 60s interval for refresh_current_session_files
- $effect on event_session_id: fires refresh_current_session_files immediately
  on session switch (no wait for next timer tick)

Propagation time: deleted/hidden files visible on remote Launchers within
~60s (session files) or ~120s (presenter files) automatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-27 20:12:10 -04:00
parent d32355a1a2
commit d3bf314c62

View File

@@ -124,6 +124,7 @@ let timer__session: any = $state(null);
let timer__presentation: any = $state(null);
let timer__presenter: any = $state(null);
let timer__file_sync: any = $state(null);
let timer__file_list: any = $state(null);
let is_syncing = false;
let show_monitor = $state(false);
@@ -196,6 +197,15 @@ onMount(async () => {
// 3. Native File Sync Loop (Dexie -> Disk)
timer__file_sync = setInterval(() => run_sync_cycle(), loop_info.file_sync);
// 4. File List Refresh Loop (API -> Dexie, prunes deleted/hidden session files)
// WHY: The presenter/session refresh loops don't fetch file lists, so deleted or
// hidden files can stay in Dexie on the Launcher machine indefinitely (until IDB is
// manually cleared). This loop calls load_ae_obj_li__event_file for the selected
// session, which triggers the stale-record pruning in _refresh_file_li_background.
// 60s matches the session/location loops; presenter files are pruned via inc_file_li
// in refresh_presenter_data which runs every 120s.
timer__file_list = setInterval(() => refresh_current_session_files(), 60000);
// Immediate first run for metadata
refresh_event_data();
run_device_heartbeat();
@@ -211,6 +221,7 @@ onMount(async () => {
setTimeout(() => refresh_session_data(), 1000);
setTimeout(() => refresh_presentation_data(), 3000);
setTimeout(() => refresh_presenter_data(), 5000);
setTimeout(() => refresh_current_session_files(), 7000);
// Clean up stale .tmp files (interrupted downloads) on startup.
// Age threshold is user-configurable (cfg → General → Cache Maintenance), default 24h.
@@ -235,6 +246,7 @@ onDestroy(() => {
if (timer__presentation) clearInterval(timer__presentation);
if (timer__presenter) clearInterval(timer__presenter);
if (timer__file_sync) clearInterval(timer__file_sync);
if (timer__file_list) clearInterval(timer__file_list);
});
// WHY: refresh_location_config() runs on a 60s timer. Without this effect,
@@ -248,6 +260,15 @@ $effect(() => {
}
});
// WHY: fires refresh_current_session_files() immediately when the operator switches
// sessions so deleted/hidden files are pruned without waiting for the 60s timer.
$effect(() => {
const session_id = $events_slct.event_session_id;
if (session_id) {
refresh_current_session_files();
}
});
// Force Sync Trigger: fetches ALL child metadata for ALL sessions in the room.
// WHY: by default, the launcher only warms presentation/presenter caches for the
// *selected* session to save bandwidth. Onsite operators use this trigger to
@@ -341,6 +362,7 @@ async function refresh_presenter_data() {
api_cfg: $ae_api,
for_obj_type: 'event_session',
for_obj_id: session_id,
inc_file_li: true, // WHY: triggers pruning of deleted/hidden presenter files in Dexie
try_cache: true,
log_lvl: 0
});
@@ -600,6 +622,29 @@ async function refresh_location_config() {
}
}
/**
* Session File List Refresh
* Fetches the file list for the SELECTED session and prunes stale/deleted/hidden records.
* WHY: The regular session/presenter refresh loops don't fetch file lists, so deleted or
* hidden files persist in the Launcher's Dexie indefinitely. This runs on a 60s timer
* and also fires immediately when the selected session changes. Presenter-level files are
* handled separately via inc_file_li=true in refresh_presenter_data (120s timer).
*/
async function refresh_current_session_files() {
if ($events_loc.launcher.sync_paused) return;
const session_id = $events_slct.event_session_id;
if (!session_id) return;
try {
await events_func.load_ae_obj_li__event_file({
api_cfg: $ae_api,
for_obj_type: 'event_session',
for_obj_id: session_id,
try_cache: true,
log_lvl: 0
});
} catch (err) {}
}
/**
* Force Location Sync
* Fetches ALL sessions and their children (presentations, presenters, files)