Skip to content

Commit baa906c

Browse files
author
Pascal Klesse
committed
fix: optimize data fetching and skeleton loading states
- Reduce polling intervals from 2s to 5s for better performance - Add selective field queries to exclude heavy log arrays - Split build detail into separate metadata and log queries - Implement conditional polling for build logs (only when running) - Fix skeleton display to show only on initial load without data - Improve loading state checks to prevent flash on subsequent refreshes
1 parent 069968b commit baa906c

File tree

8 files changed

+98
-22
lines changed

8 files changed

+98
-22
lines changed

projects/app/src/pages/index.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ const { open } = useModal();
5050
const { open: openMenu } = useContextMenu();
5151
const { currentUserState: user } = useAuthState();
5252
53-
usePolling(refresh, { interval: 2000 });
53+
usePolling(refresh, { interval: 5000 });
5454
5555
onMounted(() => {
5656
const expandedStorage = useLocalStorage<string[]>('expanded', []);
@@ -276,7 +276,7 @@ function showProjectContextMenu(project: Project) {
276276
<template>
277277
<div class="pt-[63px] w-full">
278278
<ClientOnly>
279-
<div v-if="status === 'pending'" class="flex flex-col gap-2 p-4">
279+
<div v-if="status === 'pending' && !data?.length" class="flex flex-col gap-2 p-4">
280280
<Skeleton class="h-14 w-full" />
281281
<Skeleton class="h-14 w-full" />
282282
<Skeleton class="h-14 w-full" />

projects/app/src/pages/projects/[id]/[containerId].vue

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,34 @@ const { data: project, status: projectStatus } = await useAsyncGetProjectQuery(
2525
);
2626
const projectName = computed<null | string>(() => project.value?.name || null);
2727
28+
// Only fetch fields needed for the container detail view - excludes heavy logs array
2829
const {
2930
data,
3031
refresh,
3132
status: containerStatus,
32-
} = await useAsyncGetContainerQuery({ id: containerId.value }, null, false, { lazy: true });
33+
} = await useAsyncGetContainerQuery(
34+
{ id: containerId.value },
35+
[
36+
'id',
37+
'name',
38+
'status',
39+
'kind',
40+
'url',
41+
'ssl',
42+
'exposedPort',
43+
'healthCheckCmd',
44+
'customDockerfile',
45+
'lastEditedAt',
46+
'lastDeployedAt',
47+
{ basicAuth: ['username', 'pw'] },
48+
],
49+
false,
50+
{ lazy: true },
51+
);
3352
const container = computed<Container | null>(() => data.value || null);
34-
const isLoading = computed<boolean>(() => projectStatus.value === 'pending' || containerStatus.value === 'pending');
53+
const isInitialLoading = computed<boolean>(
54+
() => (projectStatus.value === 'pending' && !project.value) || (containerStatus.value === 'pending' && !data.value),
55+
);
3556
3657
const stoppable = computed(
3758
() =>
@@ -202,7 +223,7 @@ async function get1PasswordContent() {
202223

203224
<template>
204225
<div class="w-full flex flex-col h-full">
205-
<div v-if="isLoading" class="mt-10 p-4 flex flex-col gap-4">
226+
<div v-if="isInitialLoading" class="mt-10 p-4 flex flex-col gap-4">
206227
<Skeleton class="h-10 w-full" />
207228
<Skeleton class="h-12 w-full" />
208229
<Skeleton class="h-64 w-full" />

projects/app/src/pages/projects/[id]/[containerId]/backup.vue

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ const { data: containerData, status: containerStatus } = await useAsyncGetContai
4747
false,
4848
{ lazy: true },
4949
);
50-
const isLoading = computed<boolean>(() => backupStatus.value === 'pending' || containerStatus.value === 'pending');
50+
const isInitialLoading = computed<boolean>(
51+
() =>
52+
(backupStatus.value === 'pending' && !data.value) || (containerStatus.value === 'pending' && !containerData.value),
53+
);
5154
const backup = computed<Backup>(() => data.value);
5255
const container = computed<Container>(() => containerData.value);
5356
const selectedBackup = ref(undefined);
@@ -350,7 +353,7 @@ async function uploadBackup(e: any) {
350353

351354
<template>
352355
<div class="w-full dark:text-white">
353-
<div v-if="isLoading" class="flex flex-col gap-4 p-4">
356+
<div v-if="isInitialLoading" class="flex flex-col gap-4 p-4">
354357
<Skeleton class="h-12 w-full" />
355358
<Skeleton class="h-64 w-full" />
356359
</div>

projects/app/src/pages/projects/[id]/[containerId]/builds.vue

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ const {
2121
data: buildData,
2222
refresh: refreshBuilds,
2323
status,
24-
} = await useAsyncFindBuildsForContainerQuery({ containerId: containerId.value }, null, false, { lazy: true });
24+
// Only fetch fields needed for the list - excludes heavy `log` array
25+
} = await useAsyncFindBuildsForContainerQuery(
26+
{ containerId: containerId.value },
27+
['id', 'status', 'createdAt', 'finishedAt'],
28+
false,
29+
{
30+
lazy: true,
31+
},
32+
);
2533
const builds = computed(() => buildData.value || []);
2634
27-
usePolling(refreshBuilds, { interval: 2000 });
35+
usePolling(refreshBuilds, { interval: 5000 });
2836
2937
onMounted(async () => {
3038
if (builds.value?.length) {
@@ -56,7 +64,7 @@ async function stop(id: string) {
5664

5765
<template>
5866
<div class="w-full h-full overflow-hidden relative">
59-
<div v-if="status === 'pending'" class="flex flex-col gap-2 p-4">
67+
<div v-if="status === 'pending' && !buildData?.length" class="flex flex-col gap-2 p-4">
6068
<Skeleton class="h-32 w-full" />
6169
<Skeleton class="h-32 w-full" />
6270
</div>

projects/app/src/pages/projects/[id]/[containerId]/builds/[buildId].vue

Lines changed: 52 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,65 @@ definePageMeta({
1111
breadcrumbs: 'Logs',
1212
});
1313
14+
// ============================================================================
15+
// Variables
16+
// ============================================================================
17+
1418
const route = useRoute();
1519
const buildId = ref<string>(route.params.buildId ? (route.params.buildId as string) : '');
16-
const { data: buildData, refresh: refreshBuild } = await useAsyncGetBuildQuery({ id: buildId.value }, null);
17-
const build = computed(() => buildData.value || null);
1820
19-
usePolling(
20-
async () => {
21-
if (build.value) {
22-
await refreshBuild();
21+
// Metadata query (without heavy log array)
22+
const { data: buildMeta, refresh: refreshMeta } = await useAsyncGetBuildQuery({ id: buildId.value }, [
23+
'id',
24+
'status',
25+
'createdAt',
26+
'finishedAt',
27+
]);
28+
29+
// Logs query (separate to enable conditional polling)
30+
const { data: buildLogs, refresh: refreshLogs } = await useAsyncGetBuildQuery({ id: buildId.value }, ['log']);
31+
32+
// ============================================================================
33+
// Computed Properties
34+
// ============================================================================
35+
36+
const isRunning = computed<boolean>(
37+
() => buildMeta.value?.status === BuildStatus.RUNNING || buildMeta.value?.status === BuildStatus.QUEUE,
38+
);
39+
40+
const log = computed<string[]>(() => buildLogs.value?.log ?? []);
41+
42+
// ============================================================================
43+
// Polling
44+
// ============================================================================
45+
46+
// Always poll metadata to track status changes
47+
usePolling(refreshMeta, { interval: 2000 });
48+
49+
// Conditional polling for logs - only when build is running
50+
const { pause: pauseLogPolling, resume: resumeLogPolling } = usePolling(refreshLogs, {
51+
immediate: isRunning.value,
52+
interval: 2000,
53+
});
54+
55+
// Watch for status changes to control log polling
56+
watch(
57+
isRunning,
58+
async (running: boolean, wasRunning: boolean | undefined) => {
59+
if (running) {
60+
resumeLogPolling();
61+
} else {
62+
pauseLogPolling();
63+
// Final refresh when build completes
64+
if (wasRunning) {
65+
await refreshLogs();
66+
}
2367
}
2468
},
25-
{ interval: 2000 },
69+
{ immediate: false },
2670
);
2771
</script>
2872

2973
<template>
30-
<Log class="w-full" :log="build?.log" :running="build?.status === BuildStatus.RUNNING" max-height="100%" />
74+
<Log class="w-full" :log="log" :running="isRunning" max-height="100%" />
3175
</template>

projects/app/src/pages/projects/[id]/[containerId]/logs.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ usePolling(refreshLogs, { interval: 5000 });
2424

2525
<template>
2626
<div class="w-full h-full">
27-
<div v-if="status === 'pending'" class="flex flex-col gap-2 p-4">
27+
<div v-if="status === 'pending' && !logData" class="flex flex-col gap-2 p-4">
2828
<Skeleton class="h-6 w-full" />
2929
<Skeleton class="h-6 w-full" />
3030
<Skeleton class="h-6 w-3/4" />

projects/app/src/pages/projects/[id]/[containerId]/stats.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ usePolling(refresh, { interval: 5000 });
2222

2323
<template>
2424
<div class="grid grid-cols-1 lg:grid-cols-3 gap-5 py-4 mt-4 w-full">
25-
<template v-if="status === 'pending'">
25+
<template v-if="status === 'pending' && !data">
2626
<Skeleton class="h-24 w-full" />
2727
<Skeleton class="h-24 w-full" />
2828
<Skeleton class="h-24 w-full" />

projects/app/src/pages/sources.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ function showContextMenu(source: Source) {
5555
<template>
5656
<div class="pt-[63px] w-full">
5757
<List>
58-
<template v-if="status !== 'pending'">
58+
<template v-if="status !== 'pending' || data?.length">
5959
<ListItem
6060
v-for="source of sources"
6161
:key="source?.id"
@@ -74,7 +74,7 @@ function showContextMenu(source: Source) {
7474
</ListItem>
7575
</template>
7676
<template v-else>
77-
<ListItem v-for="i of [1, 2]" :key="i" :pending="status === 'pending'" />
77+
<ListItem v-for="i of [1, 2]" :key="i" :pending="true" />
7878
</template>
7979
</List>
8080
</div>

0 commit comments

Comments
 (0)