Contraintes de code des fonctions d’orchestrateurOrchestrator function code constraints

Durable Functions est une extension d’Azure Functions qui vous permet de créer des applications avec état.Durable Functions is an extension of Azure Functions that lets you build stateful apps. Vous pouvez utiliser une fonction d’orchestrateur pour orchestrer l’exécution d’autres fonctions durables dans une application de fonction.You can use an orchestrator function to orchestrate the execution of other durable functions within a function app. Les fonctions d’orchestrateur présentent un état, sont fiables et peuvent être de longue durée.Orchestrator functions are stateful, reliable, and potentially long-running.

Contraintes du code d’orchestrateurOrchestrator code constraints

Les fonctions d’orchestrateur utilisent l’approvisionnement en événements pour garantir une exécution fiable et maintenir l’état des variables locales.Orchestrator functions use event sourcing to ensure reliable execution and to maintain local variable state. Le comportement de réexécution du code d’orchestrateur crée des contraintes sur le type de code qui peut être écrit dans une fonction d’orchestrateur.The replay behavior of orchestrator code creates constraints on the type of code that you can write in an orchestrator function. Par exemple, les fonctions d’orchestrateur doivent être déterministes : une fonction d’orchestrateur sera réexécutée à plusieurs reprises et doit générer le même résultat à chaque fois.For example, orchestrator functions must be deterministic: an orchestrator function will be replayed multiple times, and it must produce the same result each time.

Utilisation des API déterministesUsing deterministic APIs

Cette section fournit des instructions simples vous permettant de vous assurer que votre code est déterministe.This section provides some simple guidelines that help ensure your code is deterministic.

Les fonctions d’orchestrateur peuvent appeler n’importe quelle API dans son langage cible.Orchestrator functions can call any API in their target languages. Toutefois, il est important qu’elles appellent uniquement des API déterministes.However, it's important that orchestrator functions call only deterministic APIs. Une API déterministe est une API qui retourne toujours la même valeur pour la même entrée, quel que soit le moment ou la fréquence où elle est appelée.A deterministic API is an API that always returns the same value given the same input, no matter when or how often it's called.

Le tableau suivant présente des exemples d’API qui doivent être évitées, car elles ne sont pas déterministes.The following table shows examples of APIs that you should avoid because they are not deterministic. Ces restrictions s’appliquent uniquement aux fonctions d’orchestrateur.These restrictions apply only to orchestrator functions. Les autres types de fonction n’ont pas de telles restrictions.Other function types don't have such restrictions.

Catégorie d’APIAPI category MotifReason Solution de contournementWorkaround
Dates et heuresDates and times Les API qui retournent la date ou l’heure actuelle ne sont pas déterministes, car la valeur retournée est différente à chaque réexécution.APIs that return the current date or time are nondeterministic because the returned value is different for each replay. Utilisez la propriété CurrentUtcDateTime dans .NET, l’API currentUtcDateTime dans JavaScript ou l’API current_utc_datetime dans Python, sans risque pour la réexécution.Use the CurrentUtcDateTime property in .NET, the currentUtcDateTime API in JavaScript, or the current_utc_datetime API in Python, which are safe for replay.
GUID et UUIDGUIDs and UUIDs Les API qui retournent un GUID ou un UUID aléatoire ne sont pas déterministes, car la valeur générée est différente à chaque réexécution.APIs that return a random GUID or UUID are nondeterministic because the generated value is different for each replay. Utilisez NewGuid dans .NET, newGuid dans JavaScript, et new_guid dans Python pour générer des GUID aléatoires de façon sûre.Use NewGuid in .NET, newGuid in JavaScript, and new_guid in Python to safely generate random GUIDs.
Nombres aléatoiresRandom numbers Les API qui retournent des nombres aléatoires ne sont pas déterministes, car la valeur générée est différente à chaque réexécution.APIs that return random numbers are nondeterministic because the generated value is different for each replay. Utilisez une fonction d’activité pour renvoyer des nombres aléatoires à une orchestration.Use an activity function to return random numbers to an orchestration. Les valeurs de retour des fonctions d’activité sont toujours sûres pour la réexécution.The return values of activity functions are always safe for replay.
LiaisonsBindings Les liaisons d’entrée et de sortie effectuent généralement des opérations d’E/S et ne sont pas déterministes.Input and output bindings typically do I/O and are nondeterministic. Même les liaisons du client d’orchestration et du client d’entité ne doivent pas être utilisées directement par une fonction d’orchestrateur.An orchestrator function must not directly use even the orchestration client and entity client bindings. Utilisez des liaisons d’entrée et de sortie dans les fonctions clientes ou d’activité.Use input and output bindings inside client or activity functions.
RéseauNetwork Les appels réseau impliquent des systèmes externes et ne sont pas déterministes.Network calls involve external systems and are nondeterministic. Utilisez les fonctions d’activité pour effectuer des appels réseau.Use activity functions to make network calls. Si vous devez effectuer un appel HTTP à partir de votre fonction d’orchestrateur, vous pouvez également utiliser les API HTTP durables.If you need to make an HTTP call from your orchestrator function, you also can use the durable HTTP APIs.
API de blocageBlocking APIs Les API de blocage comme Thread.Sleep en .NET ou autres peuvent entraîner des problèmes de performances et de mise à l’échelle pour les fonctions d’orchestrateur et doivent être évitées.Blocking APIs like Thread.Sleep in .NET and similar APIs can cause performance and scale problems for orchestrator functions and should be avoided. Dans le plan de consommation Azure Functions, elles peuvent même entraîner des frais d’exécution inutiles.In the Azure Functions Consumption plan, they can even result in unnecessary runtime charges. Dans la mesure du possible, utilisez des alternatives aux API de blocage.Use alternatives to blocking APIs when they're available. Par exemple, utilisez CreateTimer pour introduire des délais lors de l’exécution de l’orchestration.For example, use CreateTimer to introduce delays in orchestration execution. Les retards de type minuteur durable ne sont pas pris en compte dans la durée d’exécution d’une fonction d’orchestrateur.Durable timer delays don't count towards the execution time of an orchestrator function.
API asynchronesAsync APIs Le code de l’orchestrateur ne doit jamais lancer d’opération asynchrone, sauf en utilisant l’API IDurableOrchestrationContext, l’API context.df en JavaScript ou l’API context en Python.Orchestrator code must never start any async operation except by using the IDurableOrchestrationContext API, the context.df API in JavaScript, or the context API in Python. Par exemple, on ne peut pas utiliser Task.Run, Task.Delay et HttpClient.SendAsync en .NET, ou setTimeout et setInterval en JavaScript.For example, you can't use Task.Run, Task.Delay, and HttpClient.SendAsync in .NET or setTimeout and setInterval in JavaScript. Durable Task Framework exécute le code d’orchestrateur sur un thread unique.The Durable Task Framework runs orchestrator code on a single thread. Il ne peut pas interagir avec d’autres threads pouvant être appelés par d’autres API asynchrones.It can't interact with any other threads that might be called by other async APIs. Une fonction d’orchestrateur doit effectuer uniquement des appels asynchrones durables.An orchestrator function should make only durable async calls. Tous les autres appels d’API asynchrones doivent être effectués par des fonctions d’activité.Activity functions should make any other async API calls.
Fonctions JavaScript asynchronesAsync JavaScript functions Il n’est pas possible de déclarer des fonctions d’orchestrateur JavaScript comme async, car le runtime node.js ne garantit pas que les fonctions asynchrones sont déterministes.You can't declare JavaScript orchestrator functions as async because the node.js runtime doesn't guarantee that asynchronous functions are deterministic. Déclarez les fonctions d’orchestrateur JavaScript comme fonctions de générateur synchrones.Declare JavaScript orchestrator functions as synchronous generator functions
Coroutines PythonPython Coroutines Vous ne pouvez pas déclarer des fonctions d’orchestrateur Python en tant que coroutines, c.-à-d.You can't declare Python orchestrator functions as coroutines, i.e les déclarer avec le mot clé async, car la sémantique de coroutine ne s’aligne pas sur le modèle de réexécution Durable Functions.declare them with the async keyword, because coroutine semantics do not align with the Durable Functions replay model. Déclarez les fonctions d’orchestrateur Python comme des générateurs, ce qui signifie que vous devez vous attendre à ce que l’API context utilise yield au lieu de await.Declare Python orchestrator functions as generators, meaning that you should expect the context API to use yield instead of await.
API de threadThreading APIs Durable Task Framework exécute le code d’orchestrateur sur un thread unique et ne peut pas interagir avec d’autres threads.The Durable Task Framework runs orchestrator code on a single thread and can't interact with any other threads. L’introduction de nouveaux threads dans l’exécution d’une orchestration peut entraîner des blocages ou des exécutions non déterministes.Introducing new threads into an orchestration's execution can result in nondeterministic execution or deadlocks. Les fonctions d’orchestrateur ne doivent quasiment jamais utiliser des API de thread.Orchestrator functions should almost never use threading APIs. Par exemple, dans .NET, évitez d’utiliser ConfigureAwait(continueOnCapturedContext: false). Cela garantit la poursuite de l’exécution des tâches sur le SynchronizationContext d’origine de la fonction d’orchestrateur.For example, in .NET, avoid using ConfigureAwait(continueOnCapturedContext: false); this ensures task continuations run on the orchestrator function's original SynchronizationContext. Si des API de thread sont nécessaires, limitez leur utilisation aux fonctions d’activité.If such APIs are necessary, limit their use to only activity functions.
Variables statiquesStatic variables Évitez d’utiliser des variables statiques non constantes dans les fonctions d’orchestrateur, car leurs valeurs peuvent changer au fil du temps, générant un comportement d’exécution non déterministe.Avoid using nonconstant static variables in orchestrator functions because their values can change over time, resulting in nondeterministic runtime behavior. Utilisez des constantes ou limitez l’utilisation des variables statiques aux fonctions d’activité.Use constants, or limit the use of static variables to activity functions.
Variables d'environnementEnvironment variables N’utilisez pas de variables d’environnement dans les fonctions d’orchestrateur.Don't use environment variables in orchestrator functions. Leurs valeurs peuvent changer au fil du temps, générant un comportement d’exécution non déterministe.Their values can change over time, resulting in nondeterministic runtime behavior. Les variables d’environnement doivent être référencées uniquement à partir de fonctions clientes ou de fonctions d’activité.Environment variables must be referenced only from within client functions or activity functions.
Boucles infiniesInfinite loops Evitez les boucles infinies dans les fonctions de l’orchestrateur.Avoid infinite loops in orchestrator functions. Étant donné que Durable Task Framework enregistre l’historique d’exécution à mesure que la fonction d’orchestration s’exécute, une boucle infinie risquerait de laisser une instance d’orchestrateur sans mémoire suffisante.Because the Durable Task Framework saves execution history as the orchestration function progresses, an infinite loop can cause an orchestrator instance to run out of memory. Dans les scénarios de boucle infinie, utilisez des API comme ContinueAsNew en .NET, continueAsNew en JavaScript ou continue_as_new en Python pour relancer l’exécution de la fonction et ignorer l’historique des précédentes exécutions.For infinite loop scenarios, use APIs like ContinueAsNew in .NET, continueAsNew in JavaScript, or continue_as_new in Python to restart the function execution and to discard previous execution history.

Si l’application de ces contraintes peut sembler compliquée, elles sont, dans la pratique, faciles à suivre.Although applying these constraints might seem difficult at first, in practice they're easy to follow.

Durable Task Framework tente de détecter les violations des règles mentionnées ci-dessus.The Durable Task Framework attempts to detect violations of the preceding rules. Si une violation est détectée, le framework lève une exception NonDeterministicOrchestrationException.If it finds a violation, the framework throws a NonDeterministicOrchestrationException exception. Certaines violations peuvent toutefois échapper à ce comportement de détection. Vous ne devez donc pas en dépendre.However, this detection behavior won't catch all violations, and you shouldn't depend on it.

Gestion de versionVersioning

Une orchestration durable peut s’exécuter en continu pendant des jours, des mois, des années voire même indéfiniment.A durable orchestration might run continuously for days, months, years, or even eternally. Toutes les mises à jour de code apportées aux applications Durable Functions qui affectent des orchestrations non terminées peuvent perturber le comportement de réexécution de l’orchestration.Any code updates made to Durable Functions apps that affect unfinished orchestrations might break the orchestrations' replay behavior. Il est donc important de planifier soigneusement les mises à jour du code.That's why it's important to plan carefully when making updates to code. Pour obtenir une description plus détaillée de la façon de gérer les versions de votre code, consultez l’article sur le contrôle de versions.For a more detailed description of how to version your code, see the versioning article.

Tâches durablesDurable tasks

Notes

Cette section décrit en détail l’implémentation interne de Durable Task Framework.This section describes internal implementation details of the Durable Task Framework. Vous pouvez utiliser des fonctions durables sans disposer de ces informations.You can use durable functions without knowing this information. Elles sont uniquement destinées à vous aider à mieux comprendre le comportement de réexécution.It is intended only to help you understand the replay behavior.

Les tâches qui peuvent attendre en toute sécurité dans les fonctions d’orchestrateur sont parfois appelées des tâches durables.Tasks that can safely wait in orchestrator functions are occasionally referred to as durable tasks. Durable Task Framework crée et gère ces tâches.The Durable Task Framework creates and manages these tasks. Il peut s’agir, par exemple, des tâches retournées par CallActivityAsync, WaitForExternalEvent et CreateTimer dans les fonctions d’orchestrateur .NET.Examples are the tasks returned by CallActivityAsync, WaitForExternalEvent, and CreateTimer in .NET orchestrator functions.

Ces tâches durables sont gérées en interne par une liste d’objets TaskCompletionSource en .NET.These durable tasks are internally managed by a list of TaskCompletionSource objects in .NET. Lors de la réexécution, ces tâches sont créées dans le cadre de l’exécution du code d’orchestrateur.During replay, these tasks are created as part of orchestrator code execution. Elles s’achèvent à mesure que le répartiteur énumère les événements d’historique correspondants.They're finished as the dispatcher enumerates the corresponding history events.

Les tâches s’exécutent de manière synchrone à l’aide d’un seul thread tant que tout l’historique n’a pas été réexécuté.The tasks are executed synchronously using a single thread until all the history has been replayed. Les tâches durables non terminées à la fin de la réexécution de l’historique font l’objet d’actions appropriées. Par exemple, un message peut être empilé pour appeler une fonction d’activité.Durable tasks that aren't finished by the end of history replay have appropriate actions carried out. For example, a message might be enqueued to call an activity function.

La description du comportement d’exécution faite dans cette section aide à comprendre pourquoi une fonction d’orchestrateur ne peut pas utiliser await ou yield dans une tâche non durable.This section's description of runtime behavior should help you understand why an orchestrator function can't use await or yield in a nondurable task. Il y a deux raisons à cela. Tout d’abord, le thread de répartiteur ne peut pas attendre la fin de la tâche. D’autre part, tout rappel par cette tâche risquerait d’altérer l’état de suivi de la fonction d’orchestrateur.There are two reasons: the dispatcher thread can't wait for the task to finish, and any callback by that task might potentially corrupt the tracking state of the orchestrator function. Certaines vérifications de l’exécution sont mises en œuvre pour détecter de telles violations.Some runtime checks are in place to help detect these violations.

Pour plus d’informations sur la façon dont Durable Task Framework exécute les fonctions d’orchestrateur, consultez le code source des tâches durables sur GitHub.To learn more about how the Durable Task Framework executes orchestrator functions, consult the Durable Task source code on GitHub. Consultez en particulier TaskOrchestrationExecutor.cs et TaskOrchestrationContext.cs.In particular, see TaskOrchestrationExecutor.cs and TaskOrchestrationContext.cs.

Étapes suivantesNext steps