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.
This commit is contained in:
Scott Idem
2026-02-10 18:13:16 -05:00
parent cf18257fb4
commit ddefd94f03

View File

@@ -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;