(admin) calculate size from value if not present in meta, remove atime and mtime because not present for memory driver

This commit is contained in:
Valentyne Stigloher 2025-03-16 14:28:19 +01:00
parent cf0e7de3f6
commit ad3a4879f1
4 changed files with 29 additions and 37 deletions

View File

@ -3,7 +3,7 @@ import { formatSize } from '~/src/helpers.ts';
defineProps<{ defineProps<{
chunk: string; chunk: string;
node: { size: number; atime: string; mtime: string }; size: number;
}>(); }>();
</script> </script>
@ -11,8 +11,7 @@ defineProps<{
<div class="py-1 ps-3 d-flex justify-content-between"> <div class="py-1 ps-3 d-flex justify-content-between">
<code>{{ chunk }}</code> <code>{{ chunk }}</code>
<span> <span>
<span class="badge text-bg-info">{{ formatSize(node.size) }}</span> <span class="badge text-bg-info">{{ formatSize(size) }}</span>
<span class="badge text-bg-light">{{ node.atime }}</span>
</span> </span>
</div> </div>
</template> </template>

View File

@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import { formatSize } from '~/src/helpers.ts'; import { formatSize } from '~/src/helpers.ts';
type Tree = Map<string, Tree | { size: number; atime: string; mtime: string }>; type Tree = Map<string, Tree | number>;
defineProps<{ defineProps<{
chunk: string; chunk: string;
node: Tree; tree: Tree;
}>(); }>();
const sumSize = (tree: Tree): number => { const sumSize = (tree: Tree): number => {
@ -13,20 +13,10 @@ const sumSize = (tree: Tree): number => {
if (node instanceof Map) { if (node instanceof Map) {
return sumSize(node); return sumSize(node);
} }
return node.size; return node;
}) })
.reduce((sum, size) => sum + size, 0); .reduce((sum, size) => sum + size, 0);
}; };
const minDate = (tree: Tree): Date => {
return [...tree.values()].map((node) => {
if (node instanceof Map) {
return minDate(node);
}
return new Date(node.atime);
})
.reduce((minDate, date) => minDate.getTime() <= date.getTime() ? minDate : date, new Date());
};
</script> </script>
<template> <template>
@ -35,15 +25,14 @@ const minDate = (tree: Tree): Date => {
<span class="py-1 d-inline-flex justify-content-between"> <span class="py-1 d-inline-flex justify-content-between">
<code>{{ chunk }}</code> <code>{{ chunk }}</code>
<span> <span>
<span class="badge text-bg-info">{{ formatSize(sumSize(node)) }}</span> <span class="badge text-bg-info">{{ formatSize(sumSize(tree)) }}</span>
<span class="badge text-bg-light">{{ minDate(node).toISOString() }}</span>
</span> </span>
</span> </span>
</summary> </summary>
<div class="ps-2 border-start border-secondary"> <div class="ps-2 border-start border-secondary">
<template v-for="[childChunk, childNode] of node.entries()" :key="childNode"> <template v-for="[childChunk, childNode] of tree.entries()" :key="childNode">
<AdminStorageTree v-if="childNode instanceof Map" :chunk="childChunk" :node="childNode" /> <AdminStorageTree v-if="childNode instanceof Map" :chunk="childChunk" :tree="childNode" />
<AdminStorageItem v-else :chunk="childChunk" :node="childNode" /> <AdminStorageItem v-else :chunk="childChunk" :size="childNode" />
</template> </template>
</div> </div>
</details> </details>

View File

@ -1,12 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
import AdminStorageTree from '~/components/admin/AdminStorageTree.vue'; import AdminStorageTree from '~/components/admin/AdminStorageTree.vue';
const metasAsyncData = useFetch('/api/admin/storage/metas', { lazy: true }); const sizesAsyncData = useFetch('/api/admin/storage/sizes', { lazy: true });
const tree = computed(() => { const tree = computed(() => {
const tree = new Map(); const tree = new Map();
for (const meta of metasAsyncData.data.value ?? []) { for (const [key, size] of Object.entries(sizesAsyncData.data.value ?? {})) {
const path = meta.key.split(':'); const path = key.split(':');
let subtree = tree; let subtree = tree;
for (const chunk of path.slice(0, path.length - 1)) { for (const chunk of path.slice(0, path.length - 1)) {
if (!subtree.has(chunk)) { if (!subtree.has(chunk)) {
@ -14,7 +14,7 @@ const tree = computed(() => {
} }
subtree = subtree.get(chunk); subtree = subtree.get(chunk);
} }
subtree.set(path[path.length - 1], meta); subtree.set(path[path.length - 1], size);
} }
return tree; return tree;
}); });
@ -39,15 +39,15 @@ const tree = computed(() => {
Gives an overview about mounted storages. Gives an overview about mounted storages.
</p> </p>
<button type="button" class="btn btn-outline-secondary" @click="metasAsyncData.execute()"> <button type="button" class="btn btn-outline-secondary" @click="sizesAsyncData.execute()">
<Icon v="sync" /> <Icon v="sync" />
Refresh Refresh
</button> </button>
<Loading :value="metasAsyncData.data.value"> <Loading :value="sizesAsyncData.data.value">
<template v-for="[chunk, node] of tree.entries()" :key="chunk"> <template v-for="[chunk, node] of tree.entries()" :key="chunk">
<AdminStorageTree v-if="node instanceof Map" :chunk :node /> <AdminStorageTree v-if="node instanceof Map" :chunk :tree="node" />
<AdminStorageItem v-else :chunk :node /> <AdminStorageItem v-else :chunk :size="node" />
</template> </template>
</Loading> </Loading>
</template> </template>

View File

@ -1,3 +1,12 @@
const byteLength = async (key: string): Promise<number> => {
const value = await useStorage().getItemRaw(key);
try {
return Buffer.byteLength(value);
} catch (error) {
return 0;
}
};
export default defineEventHandler(async (event) => { export default defineEventHandler(async (event) => {
const { isGranted } = await useAuthentication(event); const { isGranted } = await useAuthentication(event);
if (!isGranted('code')) { if (!isGranted('code')) {
@ -10,13 +19,8 @@ export default defineEventHandler(async (event) => {
const keys = (await useStorage().getKeys()) const keys = (await useStorage().getKeys())
.filter((key) => !key.startsWith('build') && !key.startsWith('root') && !key.startsWith('src')) .filter((key) => !key.startsWith('build') && !key.startsWith('root') && !key.startsWith('src'))
.toSorted(); .toSorted();
return await Promise.all(keys.map(async (key) => { return Object.fromEntries(await Promise.all(keys.map(async (key): Promise<[string, number]> => {
const meta = await useStorage().getMeta(key); const meta = await useStorage().getMeta(key);
return { return [key, typeof meta.size === 'number' ? meta.size : await byteLength(key)] as const;
key, })));
size: meta.size,
atime: meta.atime,
mtime: meta.mtime,
};
}));
}); });