fix(indexer): restore module-level embedding/batch constants (cronjobs cassés) #59

Merged
jcabillot merged 1 commits from fix/indexer-missing-constants into main 2026-10-17 17:11:54 -04:00
Owner

Problème

Les deux cronjobs d'indexation (mcp-maildir-cabilloteu-indexer et mcp-maildir-gmail-indexer) échouent en BackoffLimitExceeded depuis le 2026-10-16T22:00Z (4 runs consécutifs). Reproduction en clonant le pod du cronjob — échec en ~15 s :

File "/app/src/indexer.py", line 454, in <module>
    main()
File "/app/src/indexer.py", line 264, in main
    print(f"Loading embedding model: {EMBEDDING_MODEL_NAME}...")
NameError: name 'EMBEDDING_MODEL_NAME' is not defined

Les mails ne sont donc plus indexés dans Qdrant depuis le 2026-10-13 (dernier run réussi).

Cause racine

Le commit e32806a (« make indexer importable without env », mergé via #52 le 2026-10-09) a supprimé trois constantes module-level alors que main() continue de les utiliser :

EMBEDDING_MODEL_NAME = os.environ.get("EMBEDDING_MODEL_NAME", "BAAI/bge-small-en-v1.5")
BATCH_SIZE = int(os.environ.get("BATCH_SIZE", "100"))
EMBEDDING_BATCH_SIZE = int(os.environ.get("EMBEDDING_BATCH_SIZE", "64"))

Le bug est resté dormant 7 jours : le dernier run réussi tournait encore sur l'image v0.0.19-latest. Il s'est réveillé au premier tick après le bump du pin d'image à v0.0.22-latest (imagePullPolicy: Always, donc pas d'effet de cache).

server.py:37 a conservé sa propre définition, c'est pourquoi l'API MCP continuait de fonctionner.

Correctif

  • restauration des trois constantes avec leurs valeurs par défaut d'avant le refactor ;
  • tests de non-régression dans tests/test_indexer.py : constantes définies + types plausibles, et vérification que le modèle d'embedding de l'indexer est le même que celui de server.py (sinon les vecteurs stockés ne sont plus comparables aux vecteurs de requête) ;
  • ajout d'un gate ruff check src/ tests/ --select F821 dans le job unitaire de la CI : aucun test n'appelait main(), donc seule une analyse statique pouvait attraper ce cas.

Vérifications

  • ruff check --select F821 : 4 erreurs avant le correctif (sur main), 0 après.
  • pytest tests/ -q : 45 passed, 6 deselected (venv local, fastmcp 4.1.0).

Après merge

⚠️ Le pin d'image est dans tf-depl-kubernetes (modules/mcp-maildir/main.tf, lignes 177/288/372). Sans bump vers le nouveau tag v0.0.23-latest, keel ne re-rollera pas et le cronjob continuera d'exécuter le v0.0.22-latest cassé — la CI ne repeuple que le -latest du dernier tag git.

## Problème Les deux cronjobs d'indexation (`mcp-maildir-cabilloteu-indexer` et `mcp-maildir-gmail-indexer`) échouent en `BackoffLimitExceeded` depuis le **2026-10-16T22:00Z** (4 runs consécutifs). Reproduction en clonant le pod du cronjob — échec en ~15 s : ``` File "/app/src/indexer.py", line 454, in <module> main() File "/app/src/indexer.py", line 264, in main print(f"Loading embedding model: {EMBEDDING_MODEL_NAME}...") NameError: name 'EMBEDDING_MODEL_NAME' is not defined ``` Les mails ne sont donc plus indexés dans Qdrant depuis le 2026-10-13 (dernier run réussi). ## Cause racine Le commit `e32806a` (« make indexer importable without env », mergé via #52 le 2026-10-09) a supprimé trois constantes module-level alors que `main()` continue de les utiliser : ```python EMBEDDING_MODEL_NAME = os.environ.get("EMBEDDING_MODEL_NAME", "BAAI/bge-small-en-v1.5") BATCH_SIZE = int(os.environ.get("BATCH_SIZE", "100")) EMBEDDING_BATCH_SIZE = int(os.environ.get("EMBEDDING_BATCH_SIZE", "64")) ``` Le bug est resté dormant 7 jours : le dernier run réussi tournait encore sur l'image `v0.0.19-latest`. Il s'est réveillé au premier tick après le bump du pin d'image à `v0.0.22-latest` (`imagePullPolicy: Always`, donc pas d'effet de cache). `server.py:37` a conservé sa propre définition, c'est pourquoi l'API MCP continuait de fonctionner. ## Correctif - restauration des trois constantes avec leurs valeurs par défaut d'avant le refactor ; - tests de non-régression dans `tests/test_indexer.py` : constantes définies + types plausibles, et vérification que le modèle d'embedding de l'indexer est **le même que celui de `server.py`** (sinon les vecteurs stockés ne sont plus comparables aux vecteurs de requête) ; - ajout d'un gate `ruff check src/ tests/ --select F821` dans le job unitaire de la CI : aucun test n'appelait `main()`, donc seule une analyse statique pouvait attraper ce cas. ## Vérifications - `ruff check --select F821` : 4 erreurs avant le correctif (sur `main`), **0 après**. - `pytest tests/ -q` : **45 passed, 6 deselected** (venv local, fastmcp 4.1.0). ## Après merge ⚠️ Le pin d'image est dans `tf-depl-kubernetes` (`modules/mcp-maildir/main.tf`, lignes 177/288/372). Sans bump vers le nouveau tag `v0.0.23-latest`, keel ne re-rollera pas et le cronjob continuera d'exécuter le `v0.0.22-latest` cassé — la CI ne repeuple que le `-latest` du dernier tag git.
opencodecabilloteu added 1 commit 2026-10-17 17:05:00 -04:00
fix(indexer): restore module-level embedding/batch constants
PR Checks / hadolint (pull_request) Successful in 12s
Docker Build and Push / test (pull_request) Successful in 2m17s
Docker Build and Push / integration-test (pull_request) Successful in 2m38s
PR Checks / pytest (pull_request) Successful in 2m19s
Docker Build and Push / build (pull_request) Successful in 2m39s
PR Checks / build-test (pull_request) Successful in 3m5s
3b575bbf83
The "make indexer importable without env" refactor (e32806a, merged via PR
#52 on 2026-10-09) removed EMBEDDING_MODEL_NAME, BATCH_SIZE and
EMBEDDING_BATCH_SIZE from the module scope while main() kept referencing
them, so every indexer run died before reaching Qdrant:

    File "/app/src/indexer.py", line 264, in main
        print(f"Loading embedding model: {EMBEDDING_MODEL_NAME}...")
    NameError: name 'EMBEDDING_MODEL_NAME' is not defined

CI never caught it because no test executes main(). Both *-indexer cronjobs
have been failing (BackoffLimitExceeded) since 2026-10-16, i.e. the first
run after the image pin moved to v0.0.22-latest.

- restore the three constants with their pre-refactor defaults
- cover them in tests/test_indexer.py and cross-check that the indexer
  embeds with the same model as server.py (vectors must stay comparable)
- add a ruff F821 gate to the unit job so undefined names fail CI

Fixes mcp-maildir-cabilloteu-indexer and mcp-maildir-gmail-indexer.
opencodecabilloteu requested review from jcabillot 2026-10-17 17:05:20 -04:00
jcabillot merged commit e883a791fb into main 2026-10-17 17:11:54 -04:00
jcabillot deleted branch fix/indexer-missing-constants 2026-10-17 17:12:01 -04:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: perso/mcp-maildir#59