---
suivi: 1585
date: 2026-09-16
sujet: Timeouts et modèle dédiés à l’import intelligent de parcelles
chantier: foncier / parcelles / import
type: fix
statut: poussé
hash: fc035051
fichiers:
  - config/foncier.php
  - app/Services/Foncier/ParcelleImportClaudeClient.php
  - app/Services/Foncier/ParcelleImportFileExtractor.php
  - app/Services/Foncier/ParcelleImportAnalysisService.php
  - tests/Unit/ParcelleImport1585TimeoutSourceTest.php
  - tests/Unit/ParcelleImport1580SourceTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - .env.example
  - docs/suivi/SUIVI_1585_fix_timeout_import_parcelles.md
---

# SUIVI #1585 — Timeout import parcelles

## PROMPT ENVOYÉ

Panne prod : cURL error 28 after 25001 ms, 0 bytes, ParcelleImportClaudeClient.php:37.
Timeouts OCR (2 s / 25 s) trop courts pour un tableau. Aligner le modèle
sur l’OCR factures (Sonnet). Timeouts dédiés, paramétrables .env. Recalculer
le découpage sous 300 s OVH. Messages d’erreur utiles. api_log existant.
Ne pas toucher OCR factures, prompt #1580, écrans, commit, queue.

## FICHES LUES

- **#1580 LEÇON** — découpe à 20 lignes pour 25 s × n < 300 s. C’est
  précisément ce calcul, calé sur l’OCR, qui a fait échouer l’import.
  Impact : enveloppe recalculée avec timeout 120 s → 2 appels max, lots de 42.
- **#1373** — OCR connect 2 s / total 25 s, log `OCR Claude analyse` +
  `api_operation=depot_facture_ocr`. Impact : recopier le *mécanisme* de
  log, pas les constantes.

## MODÈLE

Avant correction, dans `ParcelleImportClaudeClient` L25 :
`claude-haiku-4-5-20251001` (la synthèse #1580 le citait ; le log OCR
prod utilise `claude-sonnet-4-5` dans `DepotFactureClaudeAnalysisService`).

Retenu : `claude-sonnet-4-5` (même chaîne que l’OCR factures). Tâche de
raisonnement (tableau hétérogène, type propriétaire, Pcl sup.), plus
exigeante qu’un OCR.

## CONFIGURATION

| Clé config | Env | Défaut |
|---|---|---|
| `foncier.import_parcelles.model` | `FONCIER_IMPORT_MODEL` | `claude-sonnet-4-5` |
| `foncier.import_parcelles.connect_timeout` | `FONCIER_IMPORT_CONNECT_TIMEOUT` | 5 |
| `foncier.import_parcelles.timeout` | `FONCIER_IMPORT_TIMEOUT` | 120 |
| `foncier.import_parcelles.lignes_par_lot` | `FONCIER_IMPORT_LIGNES_PAR_LOT` | 42 |
| `foncier.import_parcelles.max_execution` | `FONCIER_IMPORT_MAX_EXECUTION` | 300 |
| `foncier.import_parcelles.marge_s` | `FONCIER_IMPORT_MARGE_S` | 60 |
| `foncier.import_parcelles.max_tokens` | `FONCIER_IMPORT_MAX_TOKENS` | 16384 |

OCR factures inchangé : connect 2 s, total 25 s, Sonnet (analyse dépôt)
/ Haiku (assist `OcrFactureService`).

## CALCUL TAILLE DE LOT (plafond OVH 300 s)

```
max_execution_time web = 300 s
marge PHP (extract, rapprochement, JSON) = 60 s
budget HTTP = 300 − 60 = 240 s
timeout / appel = 120 s
max appels = floor(240 / 120) = 2
taille de lot = 42
max lignes = 2 × 42 = 84
```

Fichier Robin 83 lignes → 2 lots (42 + 41). Pire cas HTTP 240 s + 60 s
PHP = 300 s. 85 lignes → 3 lots → refusé AVANT l’appel, avec le nombre
de lignes.

20 lignes × 5 appels (#1580) × 120 s = 600 s : hors enveloppe, d’où le
changement de taille, pas seulement de timeout.

## SYNTHÈSE

Timeouts et modèle propres à l’import. api_log `parcelle_import_analyse`
(durée, modèle, tokens, HTTP, n° de lot) + log applicatif
`Parcelle import Claude analyse`. Messages : délai dépassé /
authentification / quota / indisponible / illisible — plus
« connexion impossible » sur un cURL 28. Prompt #1580 et OCR factures
non touchés.

## DÉPLOIEMENT-TEST

git pull origin main
php artisan optimize:clear
php artisan view:clear
php artisan journal:sync
(pas de migrate, pas de route:clear)

Les clés .env sont optionnelles (défauts dans config).

## LEÇON

Réutiliser le *chemin* HTTP d’un client existant n’implique pas d’en
réutiliser les timeouts. Un OCR 400 tokens ≠ un tableau de 80 lignes.
Dimensionner N_appels × timeout_pire_cas + marge PHP < max_execution_time,
et refuser avant l’appel si le fichier ne tient pas.
