Compartir vía


Orquestadores singleton con Durable Functions (Azure Functions)

Para trabajos en segundo plano, a menudo es necesario asegurarse de que solo se ejecute una instancia de un orquestador determinado a la vez. Puede asegurar este tipo de comportamiento de singleton en Durable Functions asignando un identificador de instancia determinado a un orquestador durante su creación.

Ejemplo de singleton

En el ejemplo siguiente se muestra una función de desencadenador de HTTP que crea una orquestación de trabajo en segundo plano de singleton. El código garantiza que solo existe una instancia de un identificador de instancia especificado.

[FunctionName("HttpStartSingle")]
public static async Task<HttpResponseMessage> RunSingle(
    [HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}/{instanceId}")] HttpRequestMessage req,
    [DurableClient] IDurableOrchestrationClient starter,
    string functionName,
    string instanceId,
    ILogger log)
{
    // Check if an instance with the specified ID already exists or an existing one stopped running(completed/failed/terminated).
    var existingInstance = await starter.GetStatusAsync(instanceId);
    if (existingInstance == null 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Completed 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Failed 
    || existingInstance.RuntimeStatus == OrchestrationRuntimeStatus.Terminated)
    {
        // An instance with the specified ID doesn't exist or an existing one stopped running, create one.
        dynamic eventData = await req.Content.ReadAsAsync<object>();
        await starter.StartNewAsync(functionName, instanceId, eventData);
        log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
        return starter.CreateCheckStatusResponse(req, instanceId);
    }
    else
    {
        // An instance with the specified ID exists or an existing one still running, don't create one.
        return new HttpResponseMessage(HttpStatusCode.Conflict)
        {
            Content = new StringContent($"An instance with ID '{instanceId}' already exists."),
        };
    }
}

Nota

El código de C# anterior corresponde a Durable Functions 2.x. En el caso de Durable Functions 1.x, debe usar el atributo OrchestrationClient en lugar del atributo DurableClient, además de usar el tipo de parámetro DurableOrchestrationClient en lugar de IDurableOrchestrationClient. Para obtener más información sobre las diferencias entre versiones, vea el artículo Versiones de Durable Functions.

De forma predeterminada, los identificadores de instancia son identificadores únicos globales generados aleatoriamente. Aunque en el ejemplo anterior, el identificador de instancia se pasa en los datos de ruta desde la dirección URL. A continuación, el código captura los metadatos de la instancia de orquestación para comprobar si ya se ejecutan una instancia que tiene el identificador especificado. Si no se está ejecutando dicha instancia, se crea otra instancia con ese identificador.

Nota

En este ejemplo hay una posible condición de carrera. Si dos instancias de HttpStartSingle se ejecutan simultáneamente, ambas llamadas de función notificarán un resultado satisfactorio, pero realmente solo se iniciará una instancia de orquestación. Según los requisitos, esto puede tener efectos secundarios no deseados.

Los detalles de implementación de la función de orquestador no importan realmente. Podría tratarse de una función de orquestador normal, con un principio y un final, o de una que se ejecuta sin fin (es decir, una orquestación infinita). Lo importante es que haya solo una instancia en ejecución cada vez.

Pasos siguientes