fix(documents): hard delete file in storage driver (#266)

This commit is contained in:
Corentin Thomasset
2025-04-27 14:52:05 +02:00
committed by GitHub
parent 332d836d11
commit fd44897bca
2 changed files with 24 additions and 18 deletions

View File

@@ -29,7 +29,7 @@ export function createDocumentsRepository({ db }: { db: Database }) {
getExpiredDeletedDocuments,
getOrganizationStats,
getOrganizationDocumentBySha256Hash,
getAllOrganizationTrashDocumentIds,
getAllOrganizationTrashDocuments,
updateDocument,
},
{ db },
@@ -258,6 +258,7 @@ async function getExpiredDeletedDocuments({ db, expirationDelayInDays, now = new
const documents = await db.select({
id: documentsTable.id,
originalStorageKey: documentsTable.originalStorageKey,
}).from(documentsTable).where(
and(
eq(documentsTable.isDeleted, true),
@@ -266,7 +267,7 @@ async function getExpiredDeletedDocuments({ db, expirationDelayInDays, now = new
);
return {
documentIds: documents.map(document => document.id),
documents,
};
}
@@ -312,9 +313,10 @@ async function getOrganizationStats({ organizationId, db }: { organizationId: st
};
}
async function getAllOrganizationTrashDocumentIds({ organizationId, db }: { organizationId: string; db: Database }) {
async function getAllOrganizationTrashDocuments({ organizationId, db }: { organizationId: string; db: Database }) {
const documents = await db.select({
id: documentsTable.id,
originalStorageKey: documentsTable.originalStorageKey,
}).from(documentsTable).where(
and(
eq(documentsTable.organizationId, organizationId),
@@ -323,7 +325,7 @@ async function getAllOrganizationTrashDocumentIds({ organizationId, db }: { orga
);
return {
documentIds: documents.map(document => document.id),
documents,
};
}

View File

@@ -286,17 +286,19 @@ export async function ensureDocumentExists({
}
export async function hardDeleteDocument({
documentId,
document,
documentsRepository,
documentsStorageService,
}: {
documentId: string;
document: Pick<Document, 'id' | 'originalStorageKey'>;
documentsRepository: DocumentsRepository;
documentsStorageService: DocumentStorageService;
}) {
await Promise.allSettled([
documentsRepository.hardDeleteDocument({ documentId }),
documentsStorageService.deleteFile({ storageKey: documentId }),
// TODO: use transaction
await Promise.all([
documentsRepository.hardDeleteDocument({ documentId: document.id }),
documentsStorageService.deleteFile({ storageKey: document.originalStorageKey }),
]);
}
@@ -313,23 +315,25 @@ export async function deleteExpiredDocuments({
now?: Date;
logger?: Logger;
}) {
const { documentIds } = await documentsRepository.getExpiredDeletedDocuments({
const { documents } = await documentsRepository.getExpiredDeletedDocuments({
expirationDelayInDays: config.documents.deletedDocumentsRetentionDays,
now,
});
const limit = pLimit(10);
await Promise.all(
documentIds.map(async (documentId) => {
const [, error] = await safely(hardDeleteDocument({ documentId, documentsRepository, documentsStorageService }));
documents.map(document => limit(async () => {
const [, error] = await safely(hardDeleteDocument({ document, documentsRepository, documentsStorageService }));
if (error) {
logger.error({ documentId, error }, 'Error while deleting expired document');
logger.error({ document, error }, 'Error while deleting expired document');
}
}),
})),
);
return {
deletedDocumentsCount: documentIds.length,
deletedDocumentsCount: documents.length,
};
}
@@ -354,7 +358,7 @@ export async function deleteTrashDocument({
throw createDocumentNotDeletedError();
}
await hardDeleteDocument({ documentId, documentsRepository, documentsStorageService });
await hardDeleteDocument({ document, documentsRepository, documentsStorageService });
}
export async function deleteAllTrashDocuments({
@@ -366,13 +370,13 @@ export async function deleteAllTrashDocuments({
documentsRepository: DocumentsRepository;
documentsStorageService: DocumentStorageService;
}) {
const { documentIds } = await documentsRepository.getAllOrganizationTrashDocumentIds({ organizationId });
const { documents } = await documentsRepository.getAllOrganizationTrashDocuments({ organizationId });
// TODO: refactor to use batching and transaction
const limit = pLimit(10);
await Promise.all(
documentIds.map(documentId => limit(() => hardDeleteDocument({ documentId, documentsRepository, documentsStorageService }))),
documents.map(document => limit(() => hardDeleteDocument({ document, documentsRepository, documentsStorageService }))),
);
}