디렉터리를 삭제하는 경우, 디렉터리 하위에 있던 파일의 캐시를 자동으로 삭제하도록 구현

This commit is contained in:
static
2025-01-14 03:37:31 +09:00
parent 27d2b83464
commit 4bd666a5d5
6 changed files with 51 additions and 16 deletions

View File

@@ -129,14 +129,15 @@ export const unregisterDirectory = async (userId: number, directoryId: number) =
return await db.transaction(
async (tx) => {
const unregisterFiles = async (parentId: number) => {
const files = await tx
return await tx
.delete(file)
.where(and(eq(file.userId, userId), eq(file.parentId, parentId)))
.returning({ path: file.path });
return files.map(({ path }) => path);
.returning({ id: file.id, path: file.path });
};
const unregisterDirectoryRecursively = async (directoryId: number): Promise<string[]> => {
const filePaths = await unregisterFiles(directoryId);
const unregisterDirectoryRecursively = async (
directoryId: number,
): Promise<{ id: number; path: string }[]> => {
const files = await unregisterFiles(directoryId);
const subDirectories = await tx
.select({ id: directory.id })
.from(directory)
@@ -149,7 +150,7 @@ export const unregisterDirectory = async (userId: number, directoryId: number) =
if (deleteRes.changes === 0) {
throw new IntegrityError("Directory not found");
}
return filePaths.concat(...subDirectoryFilePaths);
return files.concat(...subDirectoryFilePaths);
};
return await unregisterDirectoryRecursively(directoryId);
},

View File

@@ -15,6 +15,11 @@ export const directoryInfoResponse = z.object({
});
export type DirectoryInfoResponse = z.infer<typeof directoryInfoResponse>;
export const directoryDeleteResponse = z.object({
deletedFiles: z.number().int().positive().array(),
});
export type DirectoryDeleteResponse = z.infer<typeof directoryDeleteResponse>;
export const directoryRenameRequest = z.object({
dekVersion: z.string().datetime(),
name: z.string().base64().nonempty(),

View File

@@ -34,8 +34,13 @@ export const getDirectoryInformation = async (userId: number, directoryId: "root
export const deleteDirectory = async (userId: number, directoryId: number) => {
try {
const filePaths = await unregisterDirectory(userId, directoryId);
filePaths.map((path) => unlink(path)); // Intended
const files = await unregisterDirectory(userId, directoryId);
return {
files: files.map(({ id, path }) => {
unlink(path); // Intended
return id;
}),
};
} catch (e) {
if (e instanceof IntegrityError && e.message === "Directory not found") {
error(404, "Invalid directory id");

View File

@@ -29,7 +29,12 @@
fileInfo: getFileInfo(index.fileId, $masterKeyStore?.get(1)?.key!),
}))
.sort((a, b) => a.index.lastRetrievedAt.getTime() - b.index.lastRetrievedAt.getTime());
fileCacheTotalSize = fileCache.reduce((acc, { index }) => acc + index.size, 0);
});
$effect(() => {
if (fileCache) {
fileCacheTotalSize = fileCache.reduce((acc, { index }) => acc + index.size, 0);
}
});
</script>
@@ -39,7 +44,7 @@
<div class="flex h-full flex-col">
<TopBar title="캐시" />
{#if fileCache}
{#if fileCache && fileCache.length > 0}
<div class="space-y-4 pb-4">
<div class="space-y-1 break-keep text-gray-800">
<p>
@@ -56,7 +61,13 @@
</div>
{:else}
<div class="flex flex-grow items-center justify-center">
<p class="text-gray-500">캐시 목록을 불러오고 있어요.</p>
<p class="text-gray-500">
{#if fileCache}
캐시된 파일이 없어요.
{:else}
캐시 목록을 불러오고 있어요.
{/if}
</p>
</div>
{/if}
</div>

View File

@@ -19,6 +19,7 @@ import type {
HmacSecretListResponse,
DuplicateFileScanRequest,
DuplicateFileScanResponse,
DirectoryDeleteResponse,
} from "$lib/server/schemas";
import { hmacSecretStore, type MasterKey, type HmacSecret } from "$lib/stores";
@@ -191,6 +192,15 @@ export const requestDirectoryEntryRename = async (
};
export const requestDirectoryEntryDeletion = async (entry: SelectedDirectoryEntry) => {
await callPostApi(`/api/${entry.type}/${entry.id}/delete`);
await deleteFileCache(entry.id);
const res = await callPostApi(`/api/${entry.type}/${entry.id}/delete`);
if (!res.ok) return false;
if (entry.type === "directory") {
const { deletedFiles }: DirectoryDeleteResponse = await res.json();
await Promise.all(deletedFiles.map(deleteFileCache));
return true;
} else {
await deleteFileCache(entry.id);
return true;
}
};

View File

@@ -1,6 +1,7 @@
import { error, text } from "@sveltejs/kit";
import { error, json } from "@sveltejs/kit";
import { z } from "zod";
import { authorize } from "$lib/server/modules/auth";
import { directoryDeleteResponse, type DirectoryDeleteResponse } from "$lib/server/schemas";
import { deleteDirectory } from "$lib/server/services/directory";
import type { RequestHandler } from "./$types";
@@ -15,6 +16,8 @@ export const POST: RequestHandler = async ({ locals, params }) => {
if (!zodRes.success) error(400, "Invalid path parameters");
const { id } = zodRes.data;
await deleteDirectory(userId, id);
return text("Directory deleted", { headers: { "Content-Type": "text/plain" } });
const { files } = await deleteDirectory(userId, id);
return json(
directoryDeleteResponse.parse({ deletedFiles: files } satisfies DirectoryDeleteResponse),
);
};