perf: suppression de répertoire incrémentale au lieu du re-scan complet #BUG-113
This commit is contained in:
@@ -1312,6 +1312,52 @@ async def handle_file_move(vault_name: str, src_abs: str, dest_abs: str) -> dict
|
||||
return await update_single_file(vault_name, dest_abs)
|
||||
|
||||
|
||||
async def remove_directory_from_index(vault_name: str, dir_rel_path: str) -> int:
|
||||
"""Remove a directory subtree from the index without a full vault re-scan.
|
||||
|
||||
Incremental equivalent of ``reload_single_vault`` for deletions : every
|
||||
indexed file under *dir_rel_path* is dropped via
|
||||
``_remove_file_from_structures`` (which notifies the inverted and semantic
|
||||
indexes through the change hook), and the subtree's directory entries are
|
||||
purged from ``path_index``. Returns the number of files removed.
|
||||
|
||||
Used by :func:`api_directory_delete` — previously a ``rmtree`` was followed
|
||||
by a full vault re-scan + global inverted-index rebuild, which is linear in
|
||||
the whole vault size on every single directory deletion.
|
||||
|
||||
Args:
|
||||
vault_name: Name of the vault.
|
||||
dir_rel_path: Directory path relative to the vault root.
|
||||
|
||||
Returns:
|
||||
Number of indexed files removed.
|
||||
"""
|
||||
vault_data = index.get(vault_name)
|
||||
if not vault_data:
|
||||
return 0
|
||||
|
||||
prefix = dir_rel_path.rstrip("/") + "/"
|
||||
targets = [f["path"] for f in vault_data.get("files", []) if f["path"].startswith(prefix)]
|
||||
|
||||
lock = _get_async_lock()
|
||||
async with lock:
|
||||
removed = 0
|
||||
for rel_path in targets:
|
||||
if _remove_file_from_structures(vault_name, rel_path):
|
||||
removed += 1
|
||||
# Purge the subtree's directory entries too, otherwise empty dirs stay
|
||||
# in path_index as ghosts (file entries were removed per-file above).
|
||||
if vault_name in path_index:
|
||||
path_index[vault_name] = [
|
||||
p for p in path_index[vault_name]
|
||||
if not (p["path"] == dir_rel_path or p["path"].startswith(prefix))
|
||||
]
|
||||
|
||||
if removed:
|
||||
logger.info(f"Directory removed from index: {vault_name}/{dir_rel_path} ({removed} files)")
|
||||
return removed
|
||||
|
||||
|
||||
async def remove_vault_from_index(vault_name: str):
|
||||
"""Remove an entire vault from the index.
|
||||
|
||||
|
||||
@@ -532,9 +532,10 @@ async def api_directory_delete(
|
||||
result = service_delete_directory(vault_name, path, recursive=True)
|
||||
file_count = result["deleted_count"]
|
||||
|
||||
# Update index
|
||||
from backend.indexer import reload_single_vault
|
||||
await reload_single_vault(vault_name)
|
||||
# Update index — incremental subtree removal (no full vault re-scan, no
|
||||
# global inverted-index rebuild).
|
||||
from backend.indexer import remove_directory_from_index
|
||||
await remove_directory_from_index(vault_name, result["path"])
|
||||
|
||||
# Broadcast SSE event
|
||||
await sse_manager.broadcast("directory_deleted", {
|
||||
|
||||
Reference in New Issue
Block a user