From ddefd94f0306f4ab50860dc6e729fc27ef525f27 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 10 Feb 2026 18:13:16 -0500 Subject: [PATCH] feat(sync): implement separate API refresh loops for presentations and presenters - Added dedicated background timers for room-level presentation and presenter metadata.\n- Staggered initial data fetches to prevent request storms during room entry.\n- Cleaned up redundant timer assignments and separated API refresh from native file sync.\n- Optimized loop frequencies for better balance between freshness and performance. --- .../launcher_background_sync.svelte | 126 +++++++++++++++--- 1 file changed, 105 insertions(+), 21 deletions(-) diff --git a/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte b/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte index 1b532fe6..e55ee5d8 100644 --- a/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte +++ b/src/routes/events/[event_id]/(launcher)/launcher_background_sync.svelte @@ -22,10 +22,12 @@ // Loop Timings (Visible in UI) let loop_info = $state({ - event: 120000, + event: 90000, device: 60000, - location: 90000, - session: 45000 + location: 30000, + session: 15000, + presentation: 45000, + presenter: 60000 }); // Timer Handles @@ -33,12 +35,15 @@ let timer__device: any = $state(null); let timer__location: any = $state(null); 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 is_syncing = false; let show_monitor = $state(false); onMount(async () => { - // 1. Initial hydration of native metadata (Phase 5) + // ... (hydration logic preserved) if ($ae_loc.is_native) { try { const info = await native.get_device_info(); @@ -64,27 +69,36 @@ const dev = $ae_loc.native_device || {}; // Load timings from device config - loop_info.event = dev.check_event_loop_period || 90000; - loop_info.device = dev.check_event_device_loop_period || 60000; - loop_info.location = dev.check_event_location_loop_period || 30000; - loop_info.session = dev.check_event_session_loop_period || 10000; + loop_info.event = dev.check_event_loop_period || 120000; + loop_info.device = dev.check_event_device_loop_period || 90000; + loop_info.location = dev.check_event_location_loop_period || 60000; + loop_info.session = dev.check_event_session_loop_period || 45000; + loop_info.presentation = dev.check_event_presentation_loop_period || 90000; + loop_info.presenter = dev.check_event_presenter_loop_period || 45000; - // Timers run in both browser and native for dev/testing - timer__event = setInterval(() => run_sync_cycle(), loop_info.event); - timer__device = setInterval( - () => run_device_heartbeat(), - loop_info.device - ); - timer__location = setInterval( - () => refresh_location_config(), - loop_info.location - ); - timer__session = setInterval(() => run_sync_cycle(), loop_info.session); + // 1. Structural/Metadata Loops + timer__event = setInterval(() => refresh_event_data(), loop_info.event); + timer__device = setInterval(() => run_device_heartbeat(), loop_info.device); + timer__location = setInterval(() => refresh_location_config(), loop_info.location); - // Immediate first run - run_sync_cycle(); + // 2. Room Content Refresh Loops (API -> Dexie) + timer__session = setInterval(() => refresh_session_data(), loop_info.session); + timer__presentation = setInterval(() => refresh_presentation_data(), loop_info.presentation); + timer__presenter = setInterval(() => refresh_presenter_data(), loop_info.presenter); + + // 3. Native File Sync Loop (Dexie -> Disk) + const sync_period = dev.check_file_sync_loop_period || 10000; + timer__file_sync = setInterval(() => run_sync_cycle(), sync_period); + + // Immediate first run for metadata + refresh_event_data(); run_device_heartbeat(); refresh_location_config(); + + // Stagger initial data fetches + setTimeout(() => refresh_session_data(), 1000); + setTimeout(() => refresh_presentation_data(), 3000); + setTimeout(() => refresh_presenter_data(), 5000); }); onDestroy(() => { @@ -92,8 +106,78 @@ if (timer__device) clearInterval(timer__device); if (timer__location) clearInterval(timer__location); if (timer__session) clearInterval(timer__session); + if (timer__presentation) clearInterval(timer__presentation); + if (timer__presenter) clearInterval(timer__presenter); + if (timer__file_sync) clearInterval(timer__file_sync); }); + /** + * API Refresh: Event + */ + async function refresh_event_data() { + if (!$events_slct.event_id) return; + try { + await events_func.load_ae_obj_id__event({ + api_cfg: $ae_api, + event_id: $events_slct.event_id, + try_cache: true, + log_lvl: 0 + }); + } catch (err) {} + } + + /** + * API Refresh: Sessions in Room + */ + async function refresh_session_data() { + const location_id = $events_slct.event_location_id; + if (!location_id) return; + try { + await events_func.load_ae_obj_li__event_session({ + api_cfg: $ae_api, + for_obj_type: 'event_location', + for_obj_id: location_id, + view: 'alt', + try_cache: true, + log_lvl: 0 + }); + } catch (err) {} + } + + /** + * API Refresh: Presentations in Room + */ + async function refresh_presentation_data() { + const location_id = $events_slct.event_location_id; + if (!location_id) return; + try { + await events_func.load_ae_obj_li__event_presentation({ + api_cfg: $ae_api, + for_obj_type: 'event_location', + for_obj_id: location_id, + try_cache: true, + log_lvl: 0 + }); + } catch (err) {} + } + + /** + * API Refresh: Presenters in Room + */ + async function refresh_presenter_data() { + const location_id = $events_slct.event_location_id; + if (!location_id) return; + try { + await events_func.load_ae_obj_li__event_presenter({ + api_cfg: $ae_api, + for_obj_type: 'event_location', + for_obj_id: location_id, + try_cache: true, + log_lvl: 0 + }); + } catch (err) {} + } + async function run_sync_cycle() { const location_id = $events_slct.event_location_id; const cache_root = $ae_loc.local_file_cache_path;