mirror of
https://github.com/MODSetter/SurfSense.git
synced 2026-06-30 21:59:46 +02:00
feat: update folder deletion process to queue document deletions first and handle folder cleanup in Celery task
This commit is contained in:
parent
44e39792da
commit
fe7fcaae5d
3 changed files with 42 additions and 23 deletions
|
|
@ -367,7 +367,7 @@ async def delete_folder(
|
||||||
session: AsyncSession = Depends(get_async_session),
|
session: AsyncSession = Depends(get_async_session),
|
||||||
user: User = Depends(current_active_user),
|
user: User = Depends(current_active_user),
|
||||||
):
|
):
|
||||||
"""Delete a folder and cascade-delete subfolders. Documents are async-deleted via Celery."""
|
"""Mark documents for deletion and dispatch Celery to delete docs first, then folders."""
|
||||||
try:
|
try:
|
||||||
folder = await session.get(Folder, folder_id)
|
folder = await session.get(Folder, folder_id)
|
||||||
if not folder:
|
if not folder:
|
||||||
|
|
@ -399,30 +399,29 @@ async def delete_folder(
|
||||||
)
|
)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|
||||||
await session.execute(Folder.__table__.delete().where(Folder.id == folder_id))
|
try:
|
||||||
await session.commit()
|
from app.tasks.celery_tasks.document_tasks import (
|
||||||
|
delete_folder_documents_task,
|
||||||
|
)
|
||||||
|
|
||||||
if document_ids:
|
delete_folder_documents_task.delay(
|
||||||
try:
|
document_ids, folder_subtree_ids=list(subtree_ids)
|
||||||
from app.tasks.celery_tasks.document_tasks import (
|
)
|
||||||
delete_folder_documents_task,
|
except Exception as err:
|
||||||
)
|
if document_ids:
|
||||||
|
|
||||||
delete_folder_documents_task.delay(document_ids)
|
|
||||||
except Exception as err:
|
|
||||||
await session.execute(
|
await session.execute(
|
||||||
Document.__table__.update()
|
Document.__table__.update()
|
||||||
.where(Document.id.in_(document_ids))
|
.where(Document.id.in_(document_ids))
|
||||||
.values(status={"state": "ready"})
|
.values(status={"state": "ready"})
|
||||||
)
|
)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=503,
|
status_code=503,
|
||||||
detail="Folder deleted but document cleanup could not be queued. Documents have been restored.",
|
detail="Could not queue folder deletion. Documents have been restored.",
|
||||||
) from err
|
) from err
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"message": "Folder deleted successfully",
|
"message": "Folder deletion started",
|
||||||
"documents_queued_for_deletion": len(document_ids),
|
"documents_queued_for_deletion": len(document_ids),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -142,21 +142,30 @@ async def _delete_document_background(document_id: int) -> None:
|
||||||
retry_backoff_max=300,
|
retry_backoff_max=300,
|
||||||
max_retries=5,
|
max_retries=5,
|
||||||
)
|
)
|
||||||
def delete_folder_documents_task(self, document_ids: list[int]):
|
def delete_folder_documents_task(
|
||||||
"""Celery task to batch-delete documents orphaned by folder deletion."""
|
self,
|
||||||
|
document_ids: list[int],
|
||||||
|
folder_subtree_ids: list[int] | None = None,
|
||||||
|
):
|
||||||
|
"""Celery task to delete documents first, then the folder rows."""
|
||||||
loop = asyncio.new_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
try:
|
try:
|
||||||
loop.run_until_complete(_delete_folder_documents(document_ids))
|
loop.run_until_complete(
|
||||||
|
_delete_folder_documents(document_ids, folder_subtree_ids)
|
||||||
|
)
|
||||||
finally:
|
finally:
|
||||||
loop.close()
|
loop.close()
|
||||||
|
|
||||||
|
|
||||||
async def _delete_folder_documents(document_ids: list[int]) -> None:
|
async def _delete_folder_documents(
|
||||||
"""Delete chunks in batches, then document rows for each orphaned document."""
|
document_ids: list[int],
|
||||||
|
folder_subtree_ids: list[int] | None = None,
|
||||||
|
) -> None:
|
||||||
|
"""Delete chunks in batches, then document rows, then folder rows."""
|
||||||
from sqlalchemy import delete as sa_delete, select
|
from sqlalchemy import delete as sa_delete, select
|
||||||
|
|
||||||
from app.db import Chunk, Document
|
from app.db import Chunk, Document, Folder
|
||||||
|
|
||||||
async with get_celery_session_maker()() as session:
|
async with get_celery_session_maker()() as session:
|
||||||
batch_size = 500
|
batch_size = 500
|
||||||
|
|
@ -178,6 +187,12 @@ async def _delete_folder_documents(document_ids: list[int]) -> None:
|
||||||
await session.delete(doc)
|
await session.delete(doc)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|
||||||
|
if folder_subtree_ids:
|
||||||
|
await session.execute(
|
||||||
|
sa_delete(Folder).where(Folder.id.in_(folder_subtree_ids))
|
||||||
|
)
|
||||||
|
await session.commit()
|
||||||
|
|
||||||
|
|
||||||
@celery_app.task(
|
@celery_app.task(
|
||||||
name="delete_search_space_background",
|
name="delete_search_space_background",
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,12 @@ export function DocumentsSidebar({
|
||||||
|
|
||||||
const treeDocuments: DocumentNodeDoc[] = useMemo(() => {
|
const treeDocuments: DocumentNodeDoc[] = useMemo(() => {
|
||||||
const zeroDocs = (zeroAllDocs ?? [])
|
const zeroDocs = (zeroAllDocs ?? [])
|
||||||
.filter((d) => d.title && d.title.trim() !== "")
|
.filter((d) => {
|
||||||
|
if (!d.title || d.title.trim() === "") return false;
|
||||||
|
const state = (d.status as { state?: string } | undefined)?.state;
|
||||||
|
if (state === "deleting") return false;
|
||||||
|
return true;
|
||||||
|
})
|
||||||
.map((d) => ({
|
.map((d) => ({
|
||||||
id: d.id,
|
id: d.id,
|
||||||
title: d.title,
|
title: d.title,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue