Dans un scénario de recette, un lot de clients ERP doit être traité avant l’arrivée des commerciaux. Réparti entre plusieurs workers, l’import Dataverse alterne entre des pointes d’activité et de longues attentes. Les erreurs 429 augmentent, certains processus dorment et les fiches commerciales restent anciennes. Ajouter une instance supplémentaire semble accélérer le démarrage, puis le retard revient. Ce scénario mérite une lecture de la charge commune avant un nouvel agrandissement de l’infrastructure.
Chaque worker peut respecter sa propre limite de concurrence et contribuer malgré tout à une charge excessive. Plusieurs processus utilisant la même identité authentifiée partagent les contraintes de cette identité. Une pause appliquée dans un seul processus laisse ses voisins envoyer des appels. En pratique, le diagnostic doit commencer par la protection effectivement signalée par Dataverse. Il permet ensuite de choisir les admissions et les délais à coordonner entre les workers du middleware.
Le diagnostic porte ici sur un connecteur externe à Dataverse. Un exercice exécutable compare quatre budgets indépendants à un registre SQLite partagé, avec des tentatives concurrentes et 41 contrôles. Il montre comment réserver une place, diffuser une pause et conserver un appel dont l’issue reste inconnue. Il ne mesure aucun débit Dataverse et ne réalise aucune écriture CRM.
Ce travail relève de notre accompagnement en intégration API : relier les traitements ERP, les processus d’import et leur résultat commercial. Pour un environnement Dynamics Sales, notre expertise Microsoft Dynamics CRM permet de qualifier ensemble l’identité utilisée, le client Dataverse et les règles d’exécution du connecteur.
Pour qui : un import ralentit après sa répartition entre plusieurs workers
Reconnaître une concurrence qui échappe à chaque processus
Le signe utile est une dégradation qui accompagne le nombre d’instances, alors que chaque instance conserve ses paramètres habituels. Une reprise du catalogue, un enrichissement de contacts et un traitement de commandes peuvent appeler le même environnement sous le même utilisateur applicatif. Le nombre de tâches visibles dans un tableau de bord local décrit alors une fraction de l’activité réelle.
Deux signaux faibles justifient cette vérification : les délais de reprise s’allongent pendant que les processeurs restent disponibles, ou un petit flux métier ralentit exactement lorsque commence l’import de fond. Ces observations orientent l’enquête sans prouver sa cause. Une requête coûteuse, une logique serveur ou une connexion mal configurée peut aussi dégrader le traitement.
Délimiter le client et l’interface concernés
Nous traitons ici des appels externes à la Web API Dataverse ou au SDK .NET, avec une connexion applicative qui n’agit pas au nom d’un autre utilisateur. Les mêmes mots « Dynamics » peuvent désigner des interfaces différentes : Business Central et les applications Finance and Operations ne reprennent pas automatiquement ce contrat. Relever le service réellement appelé avant de réutiliser une limite trouvée dans une documentation voisine.
Les exemples de parallélisme côté client ne s’appliquent pas à l’intérieur d’un plug-in Dataverse. Microsoft exclut cet usage dans son guide de requêtes parallèles. Si l’import échoue sur un champ obligatoire ou une règle métier, le sujet prioritaire reste cette validation. Une réduction du nombre de workers ne rendra pas acceptable une donnée refusée.
Lire la protection signalée avant de régler la concurrence
Conserver la portée des valeurs documentées
Microsoft distingue trois protections, évaluées par utilisateur authentifié et indépendamment par serveur web de l’environnement. Les valeurs par défaut ci-dessous peuvent varier ; elles ne constituent pas une capacité globale garantie pour votre connecteur. La référence des limites de protection Dataverse décrit aussi les erreurs associées.
| Mesure | Valeur par défaut documentée |
|---|---|
| Nombre d’appels | 6 000 sur une fenêtre glissante de 300 secondes |
| Temps d’exécution cumulé | 1 200 secondes sur cette fenêtre de 300 secondes |
| Appels simultanés | 52 ou davantage, selon l’environnement |
Le contrôle de simultanéité peut refuser immédiatement un dépassement. Le comptage et le temps cumulé portent sur une fenêtre glissante. L’erreur de concurrence documentée porte le code hexadécimal 0x80072326. Conserver le diagnostic reçu permet de ne pas traiter indistinctement toutes les réponses 429 comme un manque de places simultanées.
Ne pas remplacer le temps serveur par la durée du client
Une durée mesurée autour d’un appel SDK peut inclure la latence du réseau, une pause interne ou plusieurs tentatives. Elle ne reconstitue pas le compteur de temps d’exécution de Dataverse. Un import dont les appels deviennent plus coûteux peut atteindre une autre protection sans augmentation spectaculaire de son nombre de requêtes. Le suivi doit garder durée observée, erreur native et version du client comme des informations distinctes.
Les droits de requêtes liés aux licences sont également séparés de la protection du service. Réduire une pointe n’établit pas le respect de ces allocations. Les appels groupés n’effacent pas les opérations comptabilisées à ce titre. La décision de capacité conserve donc deux questions : quelle charge le service accepte maintenant, et quelles conditions d’usage couvrent les opérations prévues.
Identifier ce que les workers partagent réellement
Rattacher les appels à un environnement et à un utilisateur effectif
Ni le nom du conteneur, ni la file consommée, ni un secret renouvelé ne définissent une nouvelle identité Dataverse. Dans le scénario serveur à serveur documenté, un environnement accepte un utilisateur applicatif par application Entra enregistrée. Inventorier les connexions permet de découvrir que des traitements présentés comme indépendants utilisent en pratique ce même compte.
La fonction WhoAmI renseigne l’utilisateur système correspondant au contexte d’exécution. Elle aide à rapprocher les configurations observées ; elle ne suffit pas à résoudre tous les cas d’impersonation, exclus de notre exemple. Associer cette information à l’environnement cible. Le registre de notre laboratoire emploiera des libellés fictifs explicites, sans les présenter comme des identifiants natifs validés.
Inclure les traitements que l’équipe ne pilote pas directement
Un ordonnanceur commun aux workers du connecteur ne voit pas nécessairement un ETL tiers ou une reprise manuelle exploitant la même identité. Demander à l’administrateur et aux équipes applicatives quels autres consommateurs existent. La limite locale choisie doit rester interprétable même lorsque la part de charge extérieure n’est pas connue ; elle ne promettra pas la disparition des refus.
Cette cartographie sert aussi au diagnostic métier. Une fiche absente depuis dix minutes peut attendre derrière un import secondaire sans que l’équipe commerciale le sache. Relier le traitement, son environnement et son identité permet de discuter une priorité avec le bon responsable. Créer d’autres comptes pour multiplier des quotas ne remplace pas cette qualification de la charge et des accès.
Utiliser le conseil de parallélisme sans le multiplier par les instances
Lire une recommandation pour l’environnement
L’en-tête x-ms-dop-hint fournit un degré de parallélisme recommandé pour l’environnement. Les clients actuels peuvent l’exposer par RecommendedDegreesOfParallelism. La documentation Microsoft sur les requêtes parallèles explique son utilisation. Cette indication ne réserve pas autant de places à chaque processus qui la lit.
Dans une configuration fictive, quatre workers autorisant chacun six appels peuvent en laisser partir vingt-quatre. Le calcul décrit le comportement de cette configuration locale ; il ne prédit pas le seuil auquel un serveur Dataverse refusera. Lorsqu’une instance supplémentaire démarre, elle doit rejoindre la politique commune, pas obtenir silencieusement un nouveau budget complet.
Choisir ce que couvre la politique du connecteur
Le budget partagé proposé porte sur les appels du connecteur dans un couple environnement–identité. Il ne reproduit pas les compteurs par serveur de Microsoft. Son réglage s’appuie sur l’indication disponible, les réponses effectivement observées et les autres consommateurs connus. La montée en charge reste progressive et mesurée sur le travail utile terminé.
La gestion de l’affinité serveur constitue un autre paramètre documenté. Elle dépend du client et de sa version ; elle ne révèle ni un nombre fixe de serveurs ni un quota global à multiplier. Copier simultanément des réglages .NET Framework et .NET moderne compliquerait encore l’analyse. Modifier un paramètre identifié, conserver sa configuration précédente et observer son effet donne un diagnostic plus exploitable.
Publier la pause dans la même transaction que la libération d’une place
Faire respecter le délai aux nouveaux départs
Avec la Web API, une réponse 429 fournit un Retry-After en secondes. Le SDK .NET représente cette information par un TimeSpan dans les détails de l’erreur. L’adaptateur doit conserver cette distinction de type avant de traduire le délai pour son ordonnanceur. Le laboratoire recevra directement une durée fictive déjà qualifiée ; il ne prétend pas parser une réponse native.
Quand un appel dont la fin est connue reçoit une pause, le registre retire sa réservation et prolonge l’échéance commune dans une seule transaction. Sinon, un voisin pourrait prendre la place libérée entre les deux opérations. L’admission lit d’abord la pause et le nombre de places occupées sous la même protection transactionnelle que l’insertion de sa réservation.
Garder l’échéance la plus tardive
À l’instant logique 10, une durée de huit secondes conduit à une échéance de 18. Une autre durée de deux secondes observée à l’instant 12 propose 14 : elle ne doit pas raccourcir la pause existante. La règle locale conserve le maximum. Deux fins simultanées sont testées avec la même logique, quelle que soit leur arrivée dans SQLite.
Cette pause interdit de nouveaux départs dans le périmètre suivi. Elle n’annule pas les requêtes déjà admises et ne suspend pas les départs d’un outil extérieur au registre. Elle ne remplace pas non plus un contrôle du rythme ou du coût des appels. Après l’échéance, une place disponible autorise un départ selon la politique locale ; Dataverse conserve la décision native d’accepter la requête.
Compter les tentatives du SDK avant d’ajouter une nouvelle boucle
Vérifier le comportement du client installé
Les classes ServiceClient et CrmServiceClient savent gérer des erreurs de protection. Avant d’ajouter un retry autour de leur appel, relever le paquet réellement installé, ses réglages et le comportement constaté. Pour ServiceClient, confronter notamment MaxRetryCount et RetryPauseTime à la version installée et à la configuration active. Un backoff ajouté par le worker peut cumuler ses attentes avec celles du SDK ; il ne doit pas raccourcir le délai demandé par le serveur.
Le permis du laboratoire représente la durée de vie d’un appel externe. Si cet appel SDK comporte plusieurs tentatives HTTP internes, il garde sa place pendant cette durée. Cela borne le nombre d’appels SDK admis par nos workers, sans donner un compteur exact des requêtes sur le réseau. Le SDK peut absorber un refus intermédiaire et ne restituer que le résultat final. Le coordinateur ne peut pas diffuser une pause qu’il n’a pas observée : vérifier qu’un point d’observation pris en charge par la version installée expose effectivement ces refus avant de concevoir une instrumentation par tentative.
Éviter une reprise qui repart pendant une attente interne
Un timeout applicatif peut expirer alors que le SDK attend encore avant une nouvelle tentative. Libérer sa place et démarrer un remplacement permettrait aux deux traitements de se chevaucher. Il faut suivre la fin effective de l’appel et qualifier son résultat. Un changement d’état de la file locale ne prouve pas l’arrêt de la requête distante.
La maîtrise de la charge ne règle pas l’unicité des écritures. Après une réponse perdue, une opération peut avoir produit un effet qu’il reste à retrouver. L’analyse des clés alternatives Dataverse et des références ERP traite cette autre frontière. Conserver ces deux contrôles évite de présenter une place d’exécution comme une preuve d’idempotence métier.
Laboratoire : huit candidats, un registre partagé et une pause visible
Exécuter une coordination locale réelle
Le programme Python complet à télécharger utilise seulement la bibliothèque standard et SQLite. Son exécution crée des bases temporaires, puis les ferme et les retire. Elle ne demande ni compte Microsoft, ni jeton, ni SDK. Les appels, environnements et utilisateurs sont des libellés fictifs. Le module SQLite de Python doit être disponible avec la prise en charge des threads.
python3 worker_admission_inventory.py
La première expérience crée quatre bases indépendantes, chacune avec une capacité fictive de deux places. Elles acceptent ensemble huit admissions. La seconde fait concourir huit threads, avec des connexions distinctes vers une même base : deux obtiennent une place, six restent refusés par la politique locale. Le test de la dernière place oppose aussi deux candidats lorsqu’une réservation existe déjà ; un seul peut gagner.
Le mécanisme critique est BEGIN IMMEDIATE, avant la lecture et l’insertion. SQLite sérialise les transactions d’écriture concurrentes sur cette base. Le nombre de places n’est donc pas lu séparément puis incrémenté sans protection. Le fichier conserve la vérification du périmètre, les erreurs et le rollback transactionnel ; l’exercice ne repose pas sur un simple compteur Python partagé.
Lire les observations sans leur attribuer une portée native
Une connexion rouverte retrouve les réservations et la pause. Un identifiant d’appel absent du registre ne libère aucune place. Un retour de l’horloge logique en arrière est refusé, et deux mises à jour concurrentes conservent l’échéance la plus tardive. Voici un extrait des champs produits par l’exécution ; le résultat complet nomme chacun des 41 contrôles.
{
"checks": 41,
"independent_admissions": 8,
"shared_admissions": 2,
"shared_pause_until": 18,
"concurrent_pause_until": 30,
"http_calls": 0,
"dataverse_requests": 0,
"crm_writes": 0,
"local_sqlite_writes": true
}
Les valeurs deux, huit et trente appartiennent au protocole local. Elles ne recommandent pas deux workers, huit retries ou trente secondes d’attente pour votre environnement. L’horloge avance à la demande des tests ; aucun temps d’attente réel n’est mesuré. Une mise en production nécessiterait notamment une horloge de référence, une gestion des processus interrompus et une observation du client Dataverse réellement employé.
Conserver une place lorsque l’appel n’est pas confirmé terminé
Ne pas transformer un délai dépassé en autorisation de remplacement
Le programme ne prévoit aucune expiration automatique de réservation. Un appel laissé sans confirmation continue d’occuper sa place, même après une grande avance de l’horloge fictive. Ce choix conservateur rend visible le problème des traitements interrompus. Il ne constitue pas une solution complète de récupération après crash : une réservation abandonnée peut bloquer durablement le travail restant.
Avant de la retirer, l’exploitation doit retrouver l’appel, établir ce qui s’est terminé et qualifier un éventuel effet distant. Une simple absence de processus local ne permet pas de conclure sur le CRM. Le runbook doit distinguer un refus connu, une réponse perdue et une opération toujours suivie par le SDK. L’action autorisée dépend de cette preuve, avec une personne responsable de l’arbitrage.
Faire échouer l’admission si le coordinateur est indisponible
Un contrôle maintient volontairement une transaction d’écriture ouverte, puis tente une admission depuis une autre connexion avec un délai SQLite court. L’échec d’acquisition du verrou d’écriture remonte comme une erreur ; aucun permis de contournement n’est créé. Remplacer une erreur de coordination par un budget local vide réintroduirait précisément la multiplication que l’expérience cherche à empêcher.
Le partage d’un fichier SQLite sur un hôte n’établit pas le comportement d’un déploiement distribué. Plusieurs machines réclament un dispositif dont l’atomicité, la disponibilité et les reprises sont qualifiées dans leur environnement. Il faut aussi prévoir la saturation du coordinateur, sa maintenance et les réservations orphelines. Le petit programme sert à discuter ces invariants avant de choisir une infrastructure.
Erreurs fréquentes qui entretiennent le ralentissement de l’import
Une instance supplémentaire peut ouvrir de nouveaux appels alors que les premières attendent leurs reprises. Paradoxalement, réduire les départs peut aider un lot en retard à progresser plus régulièrement. Cette hypothèse exige une comparaison à population et paramètres métier comparables. Le bénéfice éventuel se mesure sur les fiches correctement traitées et la durée totale du lot, sans le déduire du nombre de processus en activité.
Examiner les couches qui peuvent toutes relancer : bibliothèque HTTP, SDK, worker et ordonnanceur du lot. Une tentative applicative affichée peut recouvrir plusieurs tentatives internes. Les plafonds et délais doivent être attribués à une couche identifiée. Avant d’augmenter les instances, la personne qui règle l’autoscaling doit compter les appels toujours actifs, y compris ceux dont le SDK attend une reprise.
Un batch peut réduire certains échanges sans supprimer le temps nécessaire aux opérations. De même, une logique déclenchée côté serveur peut contribuer au coût de l’appel initial. Quand la protection porte sur le temps d’exécution, augmenter la taille des lots peut déplacer le problème. Relever les opérations coûteuses et qualifier leur forme avant d’assimiler moins d’enveloppes à moins de travail.
Microsoft précise que les en-têtes de diagnostic dont le nom commence par x-ms-ratelimit- ne doivent pas piloter le nombre d’appels envoyés ; un changement de serveur peut en réinitialiser les valeurs. Un tableau de bord qui y voit des places garanties peut libérer brutalement un nouveau lot. Conserver ces observations pour l’analyse, en les séparant des admissions décidées par le connecteur et des réponses natives.
Plan d’action : reprendre le lot sans affamer les mises à jour commerciales
Rassembler une chronologie commune avant de modifier les réglages
Commencer par une période où le ralentissement est visible et rapprocher les journaux des différents workers. Pour chaque appel suivi, conserver environnement, identité de référence, type d’opération, version du client, début, fin connue et diagnostic de reprise. Les journaux n’ont pas besoin d’embarquer les jetons ou les fiches clients complètes. Noter aussi ce que l’instrumentation ne montre pas, notamment les tentatives internes non exposées. Cette limite d’observabilité doit rester visible dans le suivi de l’import.
Le responsable de l’import fournit la population attendue et les conséquences d’un retard. L’équipe CRM identifie les automatisations serveur à examiner ; l’intégrateur décrit les dépendances et les niveaux de retry. La responsabilité du diagnostic de chaque appel doit être attribuée, en distinguant son entrée dans la file, son admission et sa fin confirmée. Cette préparation doit permettre d’expliquer pourquoi le lot attend et quelles fiches commerciales restent à jour, en attente ou rejetées. Une absence dans le CRM ne devient pas automatiquement une tâche à réémettre.
- Inventorier les workers et outils tiers qui emploient l’identité concernée, avec leurs horaires et leurs réglages actuels.
- Classifier les erreurs natives recueillies, puis conserver la distinction entre refus reçu, attente du SDK et résultat inconnu.
- Définir une politique partagée pour les nouveaux départs et la publication des pauses, sans effacer les appels déjà suivis.
- Recetter les scénarios de concurrence, de réponse perdue et d’indisponibilité du coordinateur dans un périmètre isolé.
- Ouvrir un lot borné, rapprocher ses fiches finales et vérifier que les mises à jour commerciales prioritaires progressent aussi.
- Documenter la configuration retenue, son retour arrière et le traitement des réservations restées sans issue confirmée.
Accepter une baisse des départs si le travail utile progresse
Le verdict porte sur une population rapprochée, la durée jusqu’au résultat attendu et le retard du flux commercial prioritaire. Un nombre réduit de réponses 429 n’est pas suffisant si le connecteur n’émet plus rien. À l’inverse, un refus correctement temporisé n’impose pas un échec du lot. Choisir avec le métier les seuils de retard acceptables pour la synchronisation commerciale, puis vérifier le comportement lorsque le fond et l’activité courante se chevauchent.
La priorité entre ces deux usages doit être explicite dans le futur ordonnanceur. Le laboratoire ne propose aucune garantie d’équité : un candidat peut perdre une course à une place. Réserver une progression au flux prioritaire, limiter une reprise de fond ou changer son horaire sont des choix à qualifier. Ils se mesurent sur les dossiers terminés et l’âge des attentes, avec une alerte attribuée à une équipe.
Le rollback concerne la configuration du connecteur et l’ouverture de nouveaux départs. Le runbook précise qui suspend l’entrée des tâches dans la file et qui autorise leur reprise après vérification des appels suivis. Ce retour arrière ne consiste pas à supprimer le registre pendant que des requêtes sont suivies. Conserver la version précédente des paramètres, suspendre l’élargissement du lot et laisser les opérations connues rejoindre leur état terminal. Les issues inconnues restent dans un inventaire séparé jusqu’à leur qualification ; la reprise ne repart pas du premier client par défaut.
Sources et prolongements pour recetter le connecteur Dataverse
Relier chaque réglage au contrat de son client
Les pages Microsoft sur les limites de protection et le parallélisme, citées plus haut, décrivent la portée des protections natives. La documentation de RecommendedDegreesOfParallelism, de MaxRetryCount et de RetryPauseTime complète la lecture. Ces références peuvent décrire un paquet différent de celui déployé : confronter les propriétés à votre version avant d’en modifier l’usage.
Le périmètre d’identité s’appuie sur le scénario serveur à serveur et la définition de WhoAmI. Pour l’expérience locale, les transactions SQLite expliquent la sérialisation des écritures. Aucune de ces pages ne transforme la politique proposée ici en quota distribué fourni par Microsoft.
Traiter séparément les autres causes d’un worker inopérant
Lorsqu’une exécution échoue avant tout appel Dataverse, la charge native n’est pas encore l’explication. Le diagnostic d’une pièce jointe manquante sur un worker n8n examine la disponibilité d’un fichier entre exécutions. Cette lecture aide à placer le défaut au bon endroit dans un import qui transporte aussi des documents.
Une interruption prolongée peut enfin laisser des changements non consommés. Le parcours Microsoft Graph : retrouver les mails manqués par le CRM aborde une reprise par lecture après perte de notifications, avec un contrat différent. Le point de rencontre est l’inventaire du travail restant, pas l’application des limites Dataverse à une autre plateforme.
Conclusion : piloter les départs communs et confirmer les fiches traitées
La configuration de chaque worker ne suffit pas à décrire un import réparti. Il faut retrouver l’identité effective, les autres consommateurs, les attentes déjà gérées par le client et la cause du refus reçu. Ces informations permettent de choisir une politique commune sans prétendre reconstruire les compteurs internes de Dataverse.
Les 41 contrôles exécutés confirment que des connexions concurrentes à un registre local respectent une capacité partagée et une échéance qui ne peut pas être raccourcie par une autre réponse. Ils rendent aussi visibles deux difficultés que le déploiement devra traiter : l’indisponibilité de la coordination et les réservations dont l’appel reste sans fin confirmée.
La recette native devra relier ces décisions aux fiches attendues dans le CRM, avec la version exacte du SDK et les traitements extérieurs identifiés. Un import terminé conserve la liste des fiches rapprochées et des exceptions à reprendre. Le responsable commercial peut alors connaître la fraîcheur utile de ses données, au-delà de l’état technique des workers. Notre accompagnement Dynamics CRM et applications métier cadre cette recette avec les équipes qui maintiennent l’environnement.
Dawap peut accompagner votre équipe pour concevoir et vérifier la coordination de votre intégration API Dataverse–ERP, depuis l’admission des appels jusqu’à la preuve des fiches effectivement traitées.