Skip to content

[Feature] Add file locking for concurrent manifest/index access #8

@ngmks

Description

@ngmks

🏷️ Priorité : MOYENNE | Type : Feature

Problème

Si deux sessions Claude Code démarrent simultanément (2 hooks en parallèle), les deux lancent une indexation qui :

  1. Charge le même manifest
  2. Modifie le même index LEANN
  3. Écrit le manifest → le second écrase le premier

Résultat : perte de données dans le manifest, potentielle corruption d'index.

Localisation

Fichier 1 : apps/claude_code_rag.py, méthode run() (lignes 311-362) — aucun lock
Fichier 2 : apps/claude_code_data/hooks/leann-index-sessions.sh — aucun lock

Scénario de race condition

Session A: load_manifest() → {"sessions": {s1, s2}}
Session B: load_manifest() → {"sessions": {s1, s2}}
Session A: ajoute s3, save_manifest() → {s1, s2, s3}
Session B: ajoute s4, save_manifest() → {s1, s2, s4}  ← s3 PERDU !

Correction attendue

Option 1 : Lock dans le hook (recommandé, plus simple)

# leann-index-sessions.sh
LOCK_FILE="$HOME/.leann/indexes/claude-code-sessions/.lock"
mkdir -p "$(dirname "$LOCK_FILE")"
exec 200>"$LOCK_FILE"
flock -n 200 || { echo "Index locked by another session, skipping" >&2; exit 0; }
# ... indexation ...
flock -u 200

Option 2 : Lock dans Python

import fcntl

def _with_manifest_lock(self, index_dir, callback):
    lock_path = Path(index_dir) / ".lock"
    lock_path.parent.mkdir(parents=True, exist_ok=True)
    with open(lock_path, "w") as lock_file:
        fcntl.flock(lock_file, fcntl.LOCK_EX)
        try:
            return callback()
        finally:
            fcntl.flock(lock_file, fcntl.LOCK_UN)

Critères de succès

  • Deux indexations concurrentes ne corrompent pas le manifest
  • Le lock est non-bloquant (skip gracieux si verrouillé)
  • Le fichier lock est nettoyé ou toléré s'il reste
  • Fonctionne sur Linux et macOS (flock est POSIX)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions