b7151b3bc7001415ce5603406b1507e2851f476b
6 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
b7151b3bc7 |
L6.1 : dedupliquer les chargements paresseux en vol (single-flight)
Le serveur traite les tools/call en concurrence. Les trois services a cache chargent paresseusement sans se coordonner : le premier appelant qui trouve le cache invalide lance le fetch, et tous ceux qui arrivent pendant ce fetch le trouvent *encore* invalide et lancent le leur. Une rafale de 6 appels identiques declenchait donc 6 chargements complets pour une seule cle. Ce n'est pas qu'un gaspillage : la duplication surcharge l'API AD au point de la faire echouer. Rafale mixte de 14 appels, avant correction — les 4 appels EasyWMS (~4000 workflows) reviennent en erreur, les memes passent en sequentiel : [Workflow] Error fetching workflows for "EasyWMS": POST https://10.255.255.2/AD/api/Workflow/GetByApplication failed (HTTP 500) fetching from API: 8 | EntityResolver Cache expired or empty: 3 Motif commun extrait dans src/services/single-flight.js — une Map de promesses, pas de dependance externe. Une cle par entree de cache (workflows::<app>, applications, <app>::<type>, metadata) : deux cles distinctes se chargent toujours en parallele, aucun prechargement (D26 intact). La promesse est retiree au reglement, succes *ou* echec, pour qu'un fetch en erreur ne reste pas coince. Le log de fetch reste l'observable (un par chargement reel) ; les appelants joints emettent une ligne distincte "Fetch already in flight ... joining it". --- Verifications (LIMAGRAIN), rafales rejouees 3 fois --- Phase 0, reproduction avant correction : 6 x search_workflows CustomApp -> count 44 x6, 'fetching from API' : 6 6 x query_wms_entities Container -> 6 succes, 'EntityResolver] Cache expired or empty' : 6 Rafale de 6 search_workflows {"query":"CST_","application":"CustomApp"} : ===== RUN 1 ===== ===== RUN 2 ===== ===== RUN 3 ===== id 10 success=true application=CustomApp count=44 (idem RUN 2 et RUN 3, id 11 success=true application=CustomApp count=44 les 6 reponses a 44) id 12 success=true application=CustomApp count=44 id 13 success=true application=CustomApp count=44 id 14 success=true application=CustomApp count=44 id 15 success=true application=CustomApp count=44 -- 'fetching from API' : 1 | 'joining it' : 5 [RUN 1] -- 'fetching from API' : 1 | 'joining it' : 5 [RUN 2] -- 'fetching from API' : 1 | 'joining it' : 5 [RUN 3] Rafale de 6 query_wms_entities {"entity_type":"Container","limit":1} : RUN 1/2/3 : id 10..15 success=true count=1 (6/6) -- 'EntityResolver] Cache expired or empty' : 1 | joins : 5 | GET Metadata/Entities : 5 [identique RUN 1, RUN 2, RUN 3] (avant : 6 chargements, soit 30 GET Metadata) Rafale mixte EasyWMS + CustomApp (3 + 3) — un fetch par application : RUN 1/2/3 : CustomApp count=44 x3, EasyWMS count=50 x3 [Workflow] Cache expired or empty for "CustomApp", fetching from API... [Workflow] Cache expired or empty for "EasyWMS", fetching from API... total fetch=2 joins=4 [identique RUN 1, RUN 2, RUN 3] Plus aucun HTTP 500 : un seul fetch EasyWMS concurrent au lieu de 4. Chemin sequentiel nominal, strictement inchange (driver sequentiel) : [search_workflows] success=true application=EasyWMS count=50 len=14220 [search_workflows] success=true application=EasyWMS count=50 len=14220 --- fetch=1 cached=1 joins=0 Liberation de la Map sur echec (test direct, apiService.post substitue : echoue au 1er appel, reussit ensuite) : [Workflow] Cache expired or empty for "TestApp", fetching from API... [Workflow] Fetch already in flight for "workflows::TestApp", joining it (x2) --- rafale de 3 sur un fetch en echec : appelant 0/1/2: rejected - Failed to fetch workflows ... panne reseau simulee appels reseau reels: 1 (attendu 1 : les 3 partagent le meme fetch) cache pose ? {} (attendu {} : rien en cache sur echec) --- appel suivant (la Map doit avoir ete liberee) : resultat: 1 workflow(s), appels reseau cumules: 2 Baseline : tools/list 23, resources/list 6 ; npm test 4/4 exit 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
660c62c32c |
L5.4 : rendre les autres applications visibles depuis les recherches
Cas reel du 25/08/2026 : une session Cowork cherchant des workflows CST_ sans
passer application="CustomApp" a conclu que l'AD n'en contenait aucun -- alors
que CustomApp en porte 153. Le parametre application existait bien (D26) et
etait documente ; ce qui manquait, c'est que RIEN dans la reponse ne disait
qu'on n'avait regarde qu'une application sur neuf. Un defaut silencieux se lit
comme une exhaustivite.
search_workflows et search_ad_elements rappellent desormais TOUJOURS
l'application effectivement interrogee (plus seulement quand le parametre a ete
passe), et ajoutent un hint quand la recherche revient vide.
Seuil a 0 resultat, pas "peu" : toute valeur non nulle produirait un hint
parasite sur une recherche legitimement etroite, et le mode d'echec observe est
bien le zero pris pour une absence.
Le hint nomme les autres applications depuis la liste allegee DEJA en cache ;
sans elle il reste generique et renvoie vers list_workflow_categories. Aucun
appel reseau n'est fait pour construire un hint -- ce serait exactement le
prechargement que D26 interdit.
Verifie en execution (protocole, LIMAGRAIN) :
search_workflows {"query":"CST_"} 404 chars
application: "EasyWMS", count: 0, hint nommant CustomApp et renvoyant
vers list_workflow_categories
search_workflows {"query":"CST_"} apres
list_workflow_categories 461 chars
meme hint, enrichi de la liste en cache : Common, Notifications, SmartUI,
WarehouseWebDesigner, GalileoFaults, CustomApp, User, AGV
search_workflows {"query":"CST_","application":"CustomApp"}
count: 44, application: "CustomApp" -- dont CST_SendRejectContainersToPK
search_workflows {"query":"stacker"} 14 192 -> 14 220 chars
count: 50 inchange, application: "EasyWMS" presente, aucun hint parasite
search_ad_elements Command "CST_" 457 chars
application: "EasyWMS", count: 0, meme hint
stderr : aucun fetch d'une application non demandee. Seules EasyWMS et
CustomApp sont chargees, chacune sur demande explicite.
Rebouclage complet apres modification des schemas : 23 outils, 6 resources,
les 23 noms de tools/list atteignent leur module (aucun "Unknown tool" ;
execute_command verifie statiquement, non appele car il ecrit dans le WMS),
D23 rejette toujours un parametre inconnu sur les quatre schemas modifies,
npm test 4/4 en code 0.
Lot 5 retire de la ROADMAP.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
92de85cf53 |
L4.2 : paramètre application sur les outils AD et workflow (D26)
L'application venait de WMS_APPLICATION (partagée par tous les profils) : le MCP n'interrogeait que EasyWMS, alors que CustomApp porte le spécifique client (153 workflows CST_ sur ce tenant) et que 9 applications sont déclarées par Application/GetAll. Paramètre application (défaut : l'application du profil, comportement inchangé sans lui) sur get_ad_elements, search_ad_elements, get_ad_element_details, search_workflows, get_workflow_details, list_workflow_categories. Clés de cache : ad-service passe par (application, type), workflow-service par application — sans quoi un appel CustomApp polluerait le cache EasyWMS. L'invalidation reste l'abonnement onSwitch (D8), le chargement reste paresseux (aucun préchargement des 9 applications, D10). list_workflow_categories s'adosse à Application/GetAll (liste allégée en cache : le blob data de chaque application pèse ~100 Ko) ; get_application_summary regroupe par application et ne détaille que les entrées en cache (D24), workflows compris. Acté en D26 ; CLAUDE.md mis à jour (Caches, AD), L4.2 retiré de la ROADMAP. Vérifications rejouées via le protocole (LIMAGRAIN / LIMAGRAI2512), requêtes séquentielles : - search_workflows(CST_, application:CustomApp) -> 5 objets peuplés dont CST_SendRejectContainersToPK ([Workflow] Successfully cached 153 workflows for "CustomApp"). - get_ad_elements(Workflow, application:CustomApp) -> count 153, éléments CST_* ([AD] Successfully cached 153 CustomApp::Workflow). - Séquence EasyWMS -> CustomApp -> EasyWMS sur search_workflows : 4012 vs 153, retour en cache hit ([Workflow] Using cached data for "EasyWMS"), aucune pollution ; get_application_summary montre les deux caches (workflowCachesByApplication EasyWMS 4012 / CustomApp 153). - Sans paramètre application -> comportement inchangé (W1 = W3). - switch_wms_profile EUROTRAFIC puis retour -> [Workflow] Cache cleared, [AD] All caches invalidated, [EntityResolver] Cache cleared ; summary vide. - list_workflow_categories -> 9 applications, comptes réels des applications chargées. Baseline : tools/list 23 (les 23 noms répondent), resources 6, rejet D23 d'un paramètre inconnu OK (search_workflows/applikation), npm test 4/4 exit 0. Anomalie hors périmètre consignée dans ROADMAP.md : get_workflow_details peut dépasser le seuil de rejet client (~101 800 caractères mesurés sur CST_SendRejectContainersToPK), comportement antérieur au lot. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
97ab56f928 |
L2.3 : garde-fous get_workflow_details et search_logs
Deux anomalies préexistantes au lot 1, mesurées le 24/08/2026 :
- get_workflow_details({}) renvoyait success: true avec le premier
workflow du cache : getWorkflowDetails() comparait w.Id/w.Code/w.Name,
clés qui n'existent pas sur les objets AD réels (minuscules, D5) —
undefined === undefined matchait. Clés mortes supprimées (id et name
seuls existent, les parseInt sur des GUID étaient morts aussi), garde
d'entrée rejetant workflow_id absent avec renvoi vers search_workflows.
- search_logs({}) plantait en "Cannot read properties of undefined
(reading 'toLowerCase')" : garde d'entrée nommant "keyword" avec un
exemple d'appel.
Le wrapper D23 rejette déjà ces appels via required — les gardes côté
code restent, la validation SDK n'étant pas garantie pour les appelants
directs des services.
Mesures :
- via le protocole, les deux appels {} -> "Paramètre(s) requis
manquant(s) pour ... " (wrapper D23)
- gardes appelées en direct (sans wrapper) :
getWorkflowDetails(undefined) jette "workflow_id est requis (id ou nom
exact du workflow)..." ; search_logs({}) répond success: false avec le
message nommant keyword
- get_workflow_details avec un id réel (2e workflow du cache, pas le
premier) -> objet brut complet ($id, validFrom, ..., data), id/name
conformes à la recherche
ROADMAP : L2.3 retirée, lot 2 soldé.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
3a89c317e8 |
L1.3 : aligne les projections des workflows sur les clés réelles de l'AD
Les clés réelles d'un workflow AD (relevées en direct, minuscules,
cf. D5) sont : id, name, version, applicationName, commonInfo, data…
search_workflows projetait w.Id, w.Code, w.Name, w.Category,
w.Description, w.Created, w.Modified — toutes undefined, supprimées par
JSON.stringify : 50 objets vides pour un count pourtant correct.
La projection porte désormais id, name, applicationName, version, et
les équivalents réels de created/modified trouvés dans commonInfo
(createdBy, createDate, updateDate). Code et Description n'existent
dans aucune casse : non projetés.
La notion de catégorie n'a aucun support dans les données : elle est
mappée explicitement sur applicationName, seul regroupement fourni par
l'API AD — assumé dans les descriptions d'outils et par une note dans
la réponse de list_workflow_categories, qui renvoyait 0 catégorie et
classait les 4012 workflows en « Uncategorized ». Le paramètre category
de search_workflows filtre sur applicationName. Le filtre de recherche
ne teste plus description/code, clés inexistantes.
Vérifié contre le WMS réel : search_workflows("stacker") renvoie des
objets peuplés (StackerCrane_…), list_workflow_categories renvoie
EasyWMS avec 4012 workflows, get_workflow_details renvoie toujours
l'objet brut complet (data 71 Ko).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
b59cbb3546 | version mise à jour par claude , à tester |