Fetch all Jitsi report rows

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Scott Idem
2026-05-06 14:03:47 -04:00
parent 6ebf4f125d
commit cd868460fe
2 changed files with 46 additions and 26 deletions

View File

@@ -540,6 +540,10 @@ The page now reads cached `activity_log` rows from IndexedDB first, renders that
then refreshes from the API in the background. That keeps the report usable even when the network
round-trip is slow.
Both the cache path and the API refresh now page through the full matching activity-log set in
`created_on DESC` order before building the report. That avoids the old "first 500 rows" behavior
that could hide newer sessions if the log table grew large.
### Jitsi URL Builder
Collapsible panel, visible to `trusted_access` users only. Generates properly-formatted Jitsi meeting URLs for IDAA rooms. Component: `ae_idaa_comp__jitsi_url_builder.svelte`.

View File

@@ -29,6 +29,8 @@ interface MeetingReport {
events: MeetingEvent[];
}
const JITSI_REPORT_PAGE_SIZE = 500;
// MariaDB TEXT columns come back as JSON strings from the API — parse safely.
function safe_parse_meta(raw: unknown): Record<string, unknown> {
if (!raw) return {};
@@ -89,6 +91,18 @@ function extract_participant_uuid(source: Record<string, unknown>): string {
return '';
}
function extract_flat_search_results(result: unknown): any[] {
if (Array.isArray(result)) return result;
if (
result &&
typeof result === 'object' &&
Array.isArray((result as { data?: unknown }).data)
) {
return (result as { data: any[] }).data;
}
return [];
}
/**
* @description Queries all Jitsi-related activity logs and processes them into a structured report,
* grouped by meeting ID.
@@ -287,11 +301,9 @@ function build_jitsi_report_from_logs(
export async function load_jitsi_report_from_cache({
account_id,
limit = 500,
log_lvl = 0
}: {
account_id: string;
limit?: number;
log_lvl?: number;
}): Promise<MeetingReport[] | null> {
try {
@@ -303,8 +315,7 @@ export async function load_jitsi_report_from_cache({
log.name === 'jitsi_meeting_event' ||
log.name === 'jitsi_meeting_stats'
)
.limit(limit)
.toArray();
.sortBy('created_on');
if (cached_logs.length === 0) return null;
if (
@@ -324,7 +335,7 @@ export async function load_jitsi_report_from_cache({
`Jitsi report cache hit: ${cached_logs.length} activity_log rows`
);
}
return build_jitsi_report_from_logs(cached_logs, log_lvl);
return build_jitsi_report_from_logs(cached_logs.reverse(), log_lvl);
} catch (err) {
if (log_lvl) console.warn('Jitsi report cache read failed.', err);
return null;
@@ -336,7 +347,7 @@ export async function qry__jitsi_report({
account_id,
enabled = 'all',
hidden = 'all',
limit = 500,
limit = JITSI_REPORT_PAGE_SIZE,
try_cache = true,
log_lvl = 0
}: {
@@ -359,27 +370,32 @@ export async function qry__jitsi_report({
and: [{ field: 'account_id_random', op: 'eq', value: account_id }]
};
const result = await api.search_ae_obj({
api_cfg: api_cfg,
obj_type: 'activity_log',
search_query,
headers: { 'x-account-id': account_id },
enabled,
hidden,
limit,
log_lvl: log_lvl
});
const flat_log_list: any[] = [];
const order_by_li: Record<string, 'ASC' | 'DESC'> = {
created_on: 'DESC'
};
let offset = 0;
// Handle potential V3 API envelope
let flat_log_list: any[] = [];
if (Array.isArray(result)) {
flat_log_list = result;
} else if (
result &&
typeof result === 'object' &&
Array.isArray((result as any).data)
) {
flat_log_list = (result as any).data;
while (true) {
const result = await api.search_ae_obj({
api_cfg: api_cfg,
obj_type: 'activity_log',
search_query,
headers: { 'x-account-id': account_id },
enabled,
hidden,
order_by_li,
limit,
offset,
log_lvl: log_lvl
});
const page = extract_flat_search_results(result);
if (page.length === 0) break;
flat_log_list.push(...page);
if (page.length < limit) break;
offset += limit;
}
if (