mirror of
https://github.com/papra-hq/papra.git
synced 2025-12-19 20:29:51 -06:00
fix(documents): hard delete file in storage driver (#266)
This commit is contained in:
committed by
GitHub
parent
332d836d11
commit
fd44897bca
@@ -29,7 +29,7 @@ export function createDocumentsRepository({ db }: { db: Database }) {
|
|||||||
getExpiredDeletedDocuments,
|
getExpiredDeletedDocuments,
|
||||||
getOrganizationStats,
|
getOrganizationStats,
|
||||||
getOrganizationDocumentBySha256Hash,
|
getOrganizationDocumentBySha256Hash,
|
||||||
getAllOrganizationTrashDocumentIds,
|
getAllOrganizationTrashDocuments,
|
||||||
updateDocument,
|
updateDocument,
|
||||||
},
|
},
|
||||||
{ db },
|
{ db },
|
||||||
@@ -258,6 +258,7 @@ async function getExpiredDeletedDocuments({ db, expirationDelayInDays, now = new
|
|||||||
|
|
||||||
const documents = await db.select({
|
const documents = await db.select({
|
||||||
id: documentsTable.id,
|
id: documentsTable.id,
|
||||||
|
originalStorageKey: documentsTable.originalStorageKey,
|
||||||
}).from(documentsTable).where(
|
}).from(documentsTable).where(
|
||||||
and(
|
and(
|
||||||
eq(documentsTable.isDeleted, true),
|
eq(documentsTable.isDeleted, true),
|
||||||
@@ -266,7 +267,7 @@ async function getExpiredDeletedDocuments({ db, expirationDelayInDays, now = new
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
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({
|
const documents = await db.select({
|
||||||
id: documentsTable.id,
|
id: documentsTable.id,
|
||||||
|
originalStorageKey: documentsTable.originalStorageKey,
|
||||||
}).from(documentsTable).where(
|
}).from(documentsTable).where(
|
||||||
and(
|
and(
|
||||||
eq(documentsTable.organizationId, organizationId),
|
eq(documentsTable.organizationId, organizationId),
|
||||||
@@ -323,7 +325,7 @@ async function getAllOrganizationTrashDocumentIds({ organizationId, db }: { orga
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
documentIds: documents.map(document => document.id),
|
documents,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -286,17 +286,19 @@ export async function ensureDocumentExists({
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function hardDeleteDocument({
|
export async function hardDeleteDocument({
|
||||||
documentId,
|
document,
|
||||||
documentsRepository,
|
documentsRepository,
|
||||||
documentsStorageService,
|
documentsStorageService,
|
||||||
}: {
|
}: {
|
||||||
documentId: string;
|
document: Pick<Document, 'id' | 'originalStorageKey'>;
|
||||||
documentsRepository: DocumentsRepository;
|
documentsRepository: DocumentsRepository;
|
||||||
documentsStorageService: DocumentStorageService;
|
documentsStorageService: DocumentStorageService;
|
||||||
}) {
|
}) {
|
||||||
await Promise.allSettled([
|
// TODO: use transaction
|
||||||
documentsRepository.hardDeleteDocument({ documentId }),
|
|
||||||
documentsStorageService.deleteFile({ storageKey: documentId }),
|
await Promise.all([
|
||||||
|
documentsRepository.hardDeleteDocument({ documentId: document.id }),
|
||||||
|
documentsStorageService.deleteFile({ storageKey: document.originalStorageKey }),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,23 +315,25 @@ export async function deleteExpiredDocuments({
|
|||||||
now?: Date;
|
now?: Date;
|
||||||
logger?: Logger;
|
logger?: Logger;
|
||||||
}) {
|
}) {
|
||||||
const { documentIds } = await documentsRepository.getExpiredDeletedDocuments({
|
const { documents } = await documentsRepository.getExpiredDeletedDocuments({
|
||||||
expirationDelayInDays: config.documents.deletedDocumentsRetentionDays,
|
expirationDelayInDays: config.documents.deletedDocumentsRetentionDays,
|
||||||
now,
|
now,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const limit = pLimit(10);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
documentIds.map(async (documentId) => {
|
documents.map(document => limit(async () => {
|
||||||
const [, error] = await safely(hardDeleteDocument({ documentId, documentsRepository, documentsStorageService }));
|
const [, error] = await safely(hardDeleteDocument({ document, documentsRepository, documentsStorageService }));
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
logger.error({ documentId, error }, 'Error while deleting expired document');
|
logger.error({ document, error }, 'Error while deleting expired document');
|
||||||
}
|
}
|
||||||
}),
|
})),
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
deletedDocumentsCount: documentIds.length,
|
deletedDocumentsCount: documents.length,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,7 +358,7 @@ export async function deleteTrashDocument({
|
|||||||
throw createDocumentNotDeletedError();
|
throw createDocumentNotDeletedError();
|
||||||
}
|
}
|
||||||
|
|
||||||
await hardDeleteDocument({ documentId, documentsRepository, documentsStorageService });
|
await hardDeleteDocument({ document, documentsRepository, documentsStorageService });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function deleteAllTrashDocuments({
|
export async function deleteAllTrashDocuments({
|
||||||
@@ -366,13 +370,13 @@ export async function deleteAllTrashDocuments({
|
|||||||
documentsRepository: DocumentsRepository;
|
documentsRepository: DocumentsRepository;
|
||||||
documentsStorageService: DocumentStorageService;
|
documentsStorageService: DocumentStorageService;
|
||||||
}) {
|
}) {
|
||||||
const { documentIds } = await documentsRepository.getAllOrganizationTrashDocumentIds({ organizationId });
|
const { documents } = await documentsRepository.getAllOrganizationTrashDocuments({ organizationId });
|
||||||
|
|
||||||
// TODO: refactor to use batching and transaction
|
// TODO: refactor to use batching and transaction
|
||||||
|
|
||||||
const limit = pLimit(10);
|
const limit = pLimit(10);
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
documentIds.map(documentId => limit(() => hardDeleteDocument({ documentId, documentsRepository, documentsStorageService }))),
|
documents.map(document => limit(() => hardDeleteDocument({ document, documentsRepository, documentsStorageService }))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user