Orchestrations éternelles

Les orchestrations éternelles sont des fonctions d’orchestrateur qui s’exécutent indéfiniment en réinitialisant régulièrement leur propre historique à l’aide de l’API continue-as-new . Ils sont utiles pour les agrégateurs, les travaux en arrière-plan périodiques et tout scénario Durable Functions qui nécessite une boucle infinie sans une croissance illimitée de l'historique.

Sans continue-as-new, un orchestrateur qui effectue une boucle sans fin accumulerait l’historique d’orchestration à chaque tâche planifiée, ce qui provoquerait finalement des problèmes de performances et une utilisation excessive de la mémoire. Le modèle d’orchestration sans fin résout cela en réinitialisant l’historique à chaque itération.

Note

Les exemples de code d’orchestration éternelle sont disponibles pour C#, JavaScript, Python et Java. PowerShell ne prend pas en charge continue-as-new.

Contenu de cet article :

Les orchestrations éternelles sont des orchestrations qui s’exécutent indéfiniment en réinitialisant régulièrement leur propre historique à l’aide de l’API continue-as-new . Ils sont utiles pour les agrégateurs, les travaux en arrière-plan périodiques et tout scénario nécessitant une boucle infinie sans croissance illimitée de l'historique.

Sans continue-as-new, une orchestration qui boucle indéfiniment accumulerait l'historique à chaque tâche planifiée, provoquant finalement des problèmes de performance et une utilisation excessive de la mémoire. Le modèle d’orchestration perpétuel résout cela en réinitialisant l’historique à chaque itération.

Important

Actuellement, le Kit de développement logiciel (SDK) PowerShell Durable Task n’est pas disponible.

Contenu de cet article :

Fonctionnement de "continue-as-new"

Au lieu d’utiliser des boucles infinies, les fonctions d’orchestrateur réinitialisent leur état en appelant la continue-as-new méthode de la liaison de déclencheur d’orchestration. Cette méthode prend un paramètre sérialisable JSON qui devient la nouvelle entrée pour la prochaine génération de fonction d’orchestrateur.

Lorsque vous appelez continue-as-new, l’instance d’orchestration redémarre elle-même avec la nouvelle valeur d’entrée. Le même ID d’instance est conservé, mais l’historique de la fonction d’orchestrateur est réinitialisé.

Au lieu d’utiliser des boucles infinies, les orchestrations réinitialisent leur état en appelant la continue-as-new méthode sur le contexte d’orchestration. Cette méthode prend un paramètre sérialisable JSON qui devient la nouvelle entrée pour la prochaine génération d’orchestration.

Lorsque vous appelez continue-as-new, l’instance d’orchestration redémarre elle-même avec la nouvelle valeur d’entrée. Le même ID d’instance est conservé, mais l’historique de l’orchestration est réinitialisé.

Considérations relatives à l’orchestration permanente

Gardez à l’esprit ces considérations lors de l’utilisation de la continue-as-new méthode dans une orchestration :

  • Lorsqu’une fonction d’orchestrateur est réinitialisée à l’aide de la méthode continue-as-new, le framework de tâches durables conserve le même ID d’instance, mais crée et utilise en interne un nouvel ID d’exécution. Cet identifiant d’exécution n’est pas exposé à l’extérieur, mais il est utile lors du débogage de l’exécution d’une orchestration.

  • Lorsqu’une exception non gérée se produit pendant l’exécution, l’orchestration entre dans un état d’échec et l’exécution se termine. Un appel à continue-as-new depuis un bloc finally ne redémarre pas l’orchestration après une exception non interceptée.

  • Les résultats des tâches incomplètes sont abandonnés lorsqu’une orchestration appelle continue-as-new. Par exemple, si un minuteur est programmé et que continue-as-new est appelé avant que le minuteur ne se déclenche, l’événement du minuteur est ignoré.

  • Vous pouvez facultativement conserver les événements externes non traités au cours des continue-as-new redémarrages. En C#, ContinueAsNew conserve les événements non traités par défaut. Dans Java, continueAsNew conserve également les événements par défaut. Dans Python, continue_as_new ne conserve pas les événements, sauf si save_events=True. En JavaScript, continueAsNew nécessite un saveEvents paramètre (true ou false) pour contrôler ce comportement.

Gardez à l’esprit ces considérations lors de l’utilisation de la continue-as-new méthode dans une orchestration :

  • Lorsqu’une orchestration est réinitialisée à l’aide de la continue-as-new méthode, les kits SDK Durable Task conservent le même ID d’instance, mais créent et utilisent en interne un NOUVEL ID d’exécution . Cet ID d’exécution n’est pas exposé en externe, mais il peut être utile lors du débogage de l’exécution de l’orchestration.

  • Lorsqu’une exception non gérée se produit pendant l’exécution, l’orchestration entre dans un état d’échec et l’exécution se termine. Un appel à continue-as-new partir d’un finally bloc ne redémarre pas l’orchestration après une exception non interceptée.

  • Les résultats des tâches incomplètes sont abandonnés lorsqu’une orchestration appelle continue-as-new. Par exemple, si un minuteur est programmé et que continue-as-new est appelé avant que le minuteur ne se déclenche, l’événement du minuteur est ignoré.

  • Vous pouvez facultativement conserver les événements externes non traités au cours des continue-as-new redémarrages. Dans .NET et Java, continue-as-new conserve les événements non traités par défaut. Dans Python, continue_as_new ne conserve pas les événements, sauf si save_events=True. En JavaScript, continueAsNew nécessite un saveEvents paramètre (true ou false) pour contrôler ce comportement. Dans tous les cas, les événements non traités sont transmis lorsque l’orchestration appelle waitForExternalEvent ou wait_for_external_event.

Exemple de travail périodique

Un cas d’usage courant pour les orchestrations éternelles est un travail en arrière-plan périodique, tel que les travaux de nettoyage.

Pourquoi ne pas utiliser un déclencheur de minuteur ? Un déclencheur de minuterie utilisant CRON s’exécute à des moments fixes, indépendamment de l'achèvement de l'exécution précédente. Une orchestration éternelle attend que le travail se termine avant de planifier l’itération suivante, de sorte que les exécutions ne se chevauchent jamais.

Approach Planification (intervalle de 1 heure, travail de 30 minutes) Risque de chevauchement
Déclencheur du minuteur (CRON) 1:00, 2:00, 3:00 Oui : si le travail dépasse l’intervalle
Orchestration éternelle 1:00, 2:30, 4:00 Non : l’exécution suivante attend l’achèvement
[FunctionName("Periodic_Cleanup_Loop")]
public static async Task Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    await context.CallActivityAsync("DoCleanup", null);

    // sleep for one hour between cleanups
    DateTime nextCleanup = context.CurrentUtcDateTime.AddHours(1);
    await context.CreateTimer(nextCleanup, CancellationToken.None);

    context.ContinueAsNew(null);
}
public class PeriodicCleanupLoop : TaskOrchestrator<object?, object?>
{
    public override async Task<object?> RunAsync(TaskOrchestrationContext context, object? input)
    {
        await context.CallActivityAsync("DoCleanup");

        // sleep for one hour between cleanups
        await context.CreateTimer(TimeSpan.FromHours(1), CancellationToken.None);

        context.ContinueAsNew(null);
        return null;
    }
}

Démarrer une orchestration éternelle

Utilisez la méthode client durable start-new ou schedule-new pour démarrer une orchestration éternelle, comme n’importe quelle autre fonction d’orchestration. Pour vous assurer qu’une seule instance s’exécute à la fois, utilisez un ID d’instance fixe. Pour plus d’informations, consultez orchestrations de Singleton.

[FunctionName("Trigger_Eternal_Orchestration")]
public static async Task<HttpResponseMessage> OrchestrationTrigger(
    [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestMessage request,
    [DurableClient] IDurableOrchestrationClient client)
{
    string instanceId = "StaticId";

    await client.StartNewAsync("Periodic_Cleanup_Loop", instanceId); 
    return client.CreateCheckStatusResponse(request, instanceId);
}

Utilisez la méthode client schedule-new pour démarrer une orchestration éternelle, comme n’importe quelle autre orchestration. Pour vous assurer qu’une seule instance s’exécute à la fois, utilisez un ID d’instance fixe. Pour plus d’informations, consultez orchestrations Singleton.

string instanceId = "StaticId";
await client.ScheduleNewOrchestrationInstanceAsync(
    "PeriodicCleanupLoop",
    null,
    new StartOrchestrationOptions { InstanceId = instanceId });

Sortir d'une orchestration éternelle

Si une fonction orchestratrice doit finir par se terminer, n’appelez pas continue-as-new et laissez la fonction se terminer.

Si une fonction d’orchestrateur se trouve dans une boucle infinie et doit être arrêtée, utilisez l’API de fin de la liaison du client d’orchestration pour l’arrêter.

await client.TerminateAsync(instanceId, "Cleanup no longer needed");

Pour plus d’informations, consultez Gestion des instances.

Si une orchestration doit finir par se terminer, n’appelez pas continue-as-new et laissez l’orchestration se terminer.

Si une orchestration se trouve dans une boucle infinie et doit être arrêtée, utilisez l’API de fin sur le client de tâche durable pour l’arrêter.

await client.TerminateInstanceAsync(instanceId, "Cleanup no longer needed");

Étapes suivantes