From 2571c243c9462c61bbab03094d209b7ea3071a20 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 9 Apr 2026 13:02:32 +0500 Subject: [PATCH] perf: stream slow load functions in admin pages to unblock navigation - image-gen, text-gen: books list streamed (listBooks is expensive on cold cache) - ai-jobs: jobs list streamed; add 30s cache to listAIJobs (was uncached listAll) - changelog: Gitea releases streamed on cold cache; cached path stays synchronous - admin/+layout.svelte: remove duplicate audio/translation/image-gen nav links --- ui/src/lib/server/pocketbase.ts | 11 +++- ui/src/routes/admin/+layout.svelte | 15 ------ ui/src/routes/admin/ai-jobs/+page.server.ts | 3 +- ui/src/routes/admin/ai-jobs/+page.svelte | 7 ++- ui/src/routes/admin/changelog/+page.server.ts | 32 ++++++------ ui/src/routes/admin/changelog/+page.svelte | 50 ++++++++++--------- ui/src/routes/admin/image-gen/+page.server.ts | 36 +++++++------ ui/src/routes/admin/image-gen/+page.svelte | 7 ++- ui/src/routes/admin/text-gen/+page.server.ts | 28 ++++++----- ui/src/routes/admin/text-gen/+page.svelte | 7 ++- 10 files changed, 105 insertions(+), 91 deletions(-) diff --git a/ui/src/lib/server/pocketbase.ts b/ui/src/lib/server/pocketbase.ts index c0d8c39..15deb9f 100644 --- a/ui/src/lib/server/pocketbase.ts +++ b/ui/src/lib/server/pocketbase.ts @@ -2287,10 +2287,17 @@ export async function getUserStats( // ─── AI Jobs ────────────────────────────────────────────────────────────────── +const AI_JOBS_CACHE_KEY = 'admin:ai_jobs'; +const AI_JOBS_CACHE_TTL = 30; // 30 seconds — same as other admin job lists + /** * List all AI jobs from PocketBase, sorted by started descending. - * No caching — admin views always want fresh data. + * Short-lived cache (30s) to avoid hammering PocketBase on every navigation. */ export async function listAIJobs(): Promise { - return listAll('ai_jobs', '', '-started'); + const cached = await cache.get(AI_JOBS_CACHE_KEY); + if (cached) return cached; + const jobs = await listAll('ai_jobs', '', '-started'); + await cache.set(AI_JOBS_CACHE_KEY, jobs, AI_JOBS_CACHE_TTL); + return jobs; } diff --git a/ui/src/routes/admin/+layout.svelte b/ui/src/routes/admin/+layout.svelte index 1eb75e0..a8495ef 100644 --- a/ui/src/routes/admin/+layout.svelte +++ b/ui/src/routes/admin/+layout.svelte @@ -28,21 +28,6 @@ label: () => m.admin_nav_image_gen(), icon: `` }, - { - href: '/admin/audio', - label: () => m.admin_nav_audio(), - icon: `` - }, - { - href: '/admin/translation', - label: () => m.admin_nav_translation(), - icon: `` - }, - { - href: '/admin/image-gen', - label: () => m.admin_nav_image_gen(), - icon: `` - }, { href: '/admin/text-gen', label: () => m.admin_nav_text_gen(), diff --git a/ui/src/routes/admin/ai-jobs/+page.server.ts b/ui/src/routes/admin/ai-jobs/+page.server.ts index c37bff7..f0db9d1 100644 --- a/ui/src/routes/admin/ai-jobs/+page.server.ts +++ b/ui/src/routes/admin/ai-jobs/+page.server.ts @@ -6,7 +6,8 @@ export type { AIJob }; export const load: PageServerLoad = async () => { // Parent layout already guards admin role. - const jobs = await listAIJobs().catch((e): AIJob[] => { + // Stream jobs so navigation is instant; list populates a moment later. + const jobs = listAIJobs().catch((e): AIJob[] => { log.warn('admin/ai-jobs', 'failed to load ai jobs', { err: String(e) }); return []; }); diff --git a/ui/src/routes/admin/ai-jobs/+page.svelte b/ui/src/routes/admin/ai-jobs/+page.svelte index fae1598..8fd17ae 100644 --- a/ui/src/routes/admin/ai-jobs/+page.svelte +++ b/ui/src/routes/admin/ai-jobs/+page.svelte @@ -1,5 +1,4 @@