perf(idaa): optimize search responsiveness and stabilize reactive data stream

- Stabilized the 'liveQuery' observable in 'ae_idaa_comp__event_obj_li_wrapper.svelte' by re-wrapping it in '', ensuring smooth UI updates when switching between local and API results.
- Reduced search debounce time to 250ms in '+page.svelte' for a more instantaneous user experience.
- Hardened 'Fast Path' local filtering to be more permissive and added debug logging to help diagnose IndexedDB sync issues.
- Restricted the visibility of the 'Remote First' toggle to Edit Mode (.edit_mode) for a cleaner standard user interface.
This commit is contained in:
Scott Idem
2026-01-27 14:48:08 -05:00
parent 3b6b32ce1c
commit 07e13ea5f2
3 changed files with 92 additions and 105 deletions

View File

@@ -57,6 +57,7 @@
type: $idaa_loc.recovery_meetings.qry__type,
limit: $idaa_loc.recovery_meetings.qry__limit,
order: $idaa_loc.recovery_meetings.qry__order_by,
remote: $idaa_loc.recovery_meetings.qry__remote_first,
account: $ae_loc.account_id
};
@@ -67,7 +68,7 @@
untrack(() => {
handle_search_refresh();
});
}, 350);
}, 250);
return () => {
if (search_debounce_timer) clearTimeout(search_debounce_timer);
@@ -77,72 +78,79 @@
async function handle_search_refresh() {
const current_search_id = ++last_search_id;
const account_id = $ae_loc.account_id;
const remote_first = $idaa_loc.recovery_meetings.qry__remote_first;
if (log_lvl) console.log(`[Search #${current_search_id}] Refreshing recovery meetings for account: ${account_id}...`);
if (log_lvl) console.log(`[Search #${current_search_id}] Refreshing recovery meetings (remote_first=${remote_first}) for account: ${account_id}...`);
$idaa_sess.recovery_meetings.qry__status = 'loading';
// If remote first, clear immediately to show fresh state
if (remote_first) {
event_id_random_li = [];
}
// Snapshot current params to ensure Fast Path matches revalidation
const qry_str = ($idaa_loc.recovery_meetings.qry__fulltext_str ?? '').toLowerCase().trim();
const qry_physical = $idaa_loc.recovery_meetings.qry__physical;
const qry_virtual = $idaa_loc.recovery_meetings.qry__virtual;
const qry_type = $idaa_loc.recovery_meetings.qry__type;
const remote_first = $idaa_loc.recovery_meetings.qry__remote_first;
let local_ids: string[] = [];
try {
if (account_id) {
// DEBUG: Inspect the first few items in the DB to check account_id format
if (log_lvl > 1) {
const sample = await db_events.event.limit(5).toArray();
console.log(`[Search #${current_search_id}] DB Sample:`, sample.map(s => ({id: s.id, acct: s.account_id, acct_r: s.account_id_random})));
}
// 1. FAST PATH: Local IDB Search (SWR Pattern) - Skip if Remote First
if (!remote_first) {
try {
if (account_id) {
let local_results = await db_events.event
.filter(ev => {
// Resilient account check: match either account_id or account_id_random
const acct_match = ev.account_id === account_id || ev.account_id_random === account_id;
if (!acct_match) return false;
let local_results = await db_events.event
.filter(ev => {
// Resilient account check: match either account_id or account_id_random
const acct_match = ev.account_id === account_id || ev.account_id_random === account_id;
if (!acct_match) return false;
if (qry_type && ev.type !== qry_type) return false;
if (qry_physical || qry_virtual) {
let match = false;
if (qry_physical && ev.physical) match = true;
if (qry_virtual && ev.virtual) match = true;
if (!match) return false;
}
if (qry_str) {
const name = (ev.name ?? '').toLowerCase();
const desc = (ev.description ?? '').toLowerCase();
const loc = (ev.location_text ?? '').toLowerCase();
return name.includes(qry_str) || desc.includes(qry_str) || loc.includes(qry_str);
}
return true;
})
.toArray();
if (qry_type && ev.type !== qry_type) return false;
if (qry_physical || qry_virtual) {
let match = false;
if (qry_physical && ev.physical) match = true;
if (qry_virtual && ev.virtual) match = true;
if (!match) return false;
// Sort local results
if ($idaa_loc.recovery_meetings.qry__order_by === 'name') {
local_results.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''));
} else {
local_results.sort((a, b) => {
const dateA = a.updated_on ? new Date(a.updated_on).getTime() : 0;
const dateB = b.updated_on ? new Date(b.updated_on).getTime() : 0;
return dateB - dateA;
});
}
local_ids = local_results.map(e => e.id || e.event_id_random).filter(Boolean);
// Update UI immediately with local results
if (current_search_id === last_search_id) {
if (log_lvl) console.log(`[Search #${current_search_id}] Fast Path complete. Found ${local_ids.length} items locally.`);
event_id_random_li = local_ids;
// If we found results locally, we can mark as done to stop spinning,
// revalidation will still finish in background
if (local_ids.length > 0) {
$idaa_sess.recovery_meetings.qry__status = 'done';
}
if (qry_str) {
const name = (ev.name ?? '').toLowerCase();
const desc = (ev.description ?? '').toLowerCase();
const loc = (ev.location_text ?? '').toLowerCase();
return name.includes(qry_str) || desc.includes(qry_str) || loc.includes(qry_str);
}
return true;
})
.toArray();
// Sort local results
if ($idaa_loc.recovery_meetings.qry__order_by === 'name') {
local_results.sort((a, b) => (a.name ?? '').localeCompare(b.name ?? ''));
} else {
local_results.sort((a, b) => {
const dateA = a.updated_on ? new Date(a.updated_on).getTime() : 0;
const dateB = b.updated_on ? new Date(b.updated_on).getTime() : 0;
return dateB - dateA;
});
}
local_ids = local_results.map(e => e.event_id_random || e.id).filter(Boolean);
// Update UI immediately with local results
if (current_search_id === last_search_id) {
if (log_lvl) console.log(`[Search #${current_search_id}] Fast Path complete. Found ${local_ids.length} items locally.`);
event_id_random_li = local_ids;
}
}
} catch (e) {
if (log_lvl) console.warn('Fast Path failed, waiting for API...', e);
}
} catch (e) {
if (log_lvl) console.warn('Fast Path failed, waiting for API...', e);
}
// 2. REVALIDATE: Slow API Request
@@ -165,7 +173,7 @@
if (current_search_id === last_search_id) {
const api_results = results || [];
const api_ids = api_results.map((e: any) => e.event_id_random).filter(Boolean);
const api_ids = api_results.map((e: any) => e.id || e.event_id_random).filter(Boolean);
// If API returns 0 but local search found broad results, protect the UI
if (api_ids.length === 0 && local_ids.length > 0 && !remote_first && !qry_str) {