Encadeamento de funções nas Funções Duráveis – Exemplo se sequência Hello
Artigo
Encadeamento de funções é o padrão de executar uma sequência de funções em uma ordem específica. Frequentemente, a saída de uma função precisa ser aplicada à entrada de outra função. Esse artigo descreve a sequência de encadeamento que você cria ao executar o início rápido do Durable Functions (C#, JavaScript, TypeScript, Python, PowerShell ou Java). Para obter mais informações sobre as funções duráveis, consulte visão geral das funções duráveis.
A versão 4 do modelo de programação Node.js para o Azure Functions está em disponibilidade geral. O novo modelo v4 é projetado para oferecer uma experiência mais flexível e intuitiva para desenvolvedores de JavaScript e TypeScript. Saiba mais sobre as diferenças entre v3 e v4 na guia de migração.
Nos trechos de código a seguir, o JavaScript (PM4) denota o modelo de programação V4, a nova experiência.
As funções
Este artigo explica as seguintes funções no aplicativo de exemplo:
E1_HelloSequence: uma função de orquestrador que chamas E1_SayHello várias vezes em uma sequência. Ela armazena as saídas das chamadas E1_SayHello e registra os resultados.
E1_SayHello: uma função de atividade que precede uma cadeia de caracteres com "Hello".
HttpStart: uma função de cliente durável disparada por HTTP que inicia uma instância do orquestrador.
Todas as funções de orquestração em C# devem ter um parâmetro do tipo DurableOrchestrationContext, que existe no assembly Microsoft.Azure.WebJobs.Extensions.DurableTask. Esse objeto de contexto permite chamar outras funções de atividade e passar parâmetros de entrada usando o método CallActivityAsync.
O código chama E1_SayHello três vezes seguidas com valores de parâmetros diferentes. O valor retornado de cada chamada é adicionado à lista outputs, que é retornada ao final da função.
function.json
Se você usa o Visual Studio Code ou o portal do Azure para desenvolvimento, este é o conteúdo do arquivo function.json para a função de orquestrador. A maioria dos arquivos function.json do orquestrador são quase exatamente iguais a esse.
O importante é o tipo de associação de orchestrationTrigger. Todas as funções de orquestrador devem usar esse tipo de gatilho.
Aviso
Para obedecer a regra de "não fazer E/S" das funções de orquestrador, não use nenhuma associação de entrada ou saída ao usar a associação de gatilho orchestrationTrigger. Se outras associações de entrada ou de saída forem necessárias, elas deverão ser usadas no contexto das funções activityTrigger, que são chamadas pelo orquestrador. Para obter mais informações, confira o artigo Restrições de código na função de orquestrador.
Todas as funções de orquestração de JavaScript devem incluir o módulo durable-functions. É uma biblioteca que permite escrever Durable Functions em JavaScript. Há três diferenças significativas entre uma função de orquestrador e outras funções de JavaScript:
A função é encapsulada em uma chamada para o método orchestrator do módulo durable-functions (aqui df).
A função deve ser síncrona. Como o método "orchestrator" lida com a chamada final "context.done", a função deve simplesmente "return".
O objeto context contém um objeto de contexto de orquestração durável df que permite chamar outras funções de atividade e passa parâmetros de entrada usando o método callActivity. O código chama E1_SayHello três vezes em sequência com valores de parâmetros diferentes, usando yield para indicar que a execução deve aguardar as chamadas de função de atividade assíncrona serem retornadas. O valor retornado de cada chamada é adicionado à matriz outputs, que é retornada ao final da função.
Todas as funções de orquestração de JavaScript devem incluir o módulo durable-functions. Esse módulo permite que você escreva Durable Functions em JavaScript. Para usar o modelo de programação de nós V4, você precisa instalar a versão prévia v3.x da versão do durable-functions.
Há duas diferenças significativas entre uma função do orquestrador e outras funções em JavaScript:
A função deve ser síncrona. A função deve simplesmente "retornar".
O objeto context contém um objeto de contexto de orquestração durável df que permite chamar outras funções de atividade e passa parâmetros de entrada usando o método callActivity. O código chama sayHello três vezes em sequência com valores de parâmetros diferentes, usando yield para indicar que a execução deve aguardar as chamadas de função de atividade assíncrona serem retornadas. O valor retornado de cada chamada é adicionado à matriz outputs, que é retornada ao final da função.
Observação
Durable Functions em Python estão disponíveis apenas para o runtime do Functions 3.0.
function.json
Se você usa o Visual Studio Code ou o portal do Azure para desenvolvimento, este é o conteúdo do arquivo function.json para a função de orquestrador. A maioria dos arquivos function.json do orquestrador são quase exatamente iguais a esse.
O importante é o tipo de associação de orchestrationTrigger. Todas as funções de orquestrador devem usar esse tipo de gatilho.
Aviso
Para obedecer a regra de "não fazer E/S" das funções de orquestrador, não use nenhuma associação de entrada ou saída ao usar a associação de gatilho orchestrationTrigger. Se outras associações de entrada ou de saída forem necessárias, elas deverão ser usadas no contexto das funções activityTrigger, que são chamadas pelo orquestrador. Para obter mais informações, confira o artigo Restrições de código na função de orquestrador.
Todas as funções de orquestração do Python devem incluir o durable-functions pacote. É uma biblioteca que permite escrever Durable Functions em Python. Há duas diferenças significativas entre uma função de orquestrador e outras funções de Python:
O arquivo deve registrar a função de orquestrador como um orquestrador, indicando main = df.Orchestrator.create(<orchestrator function name>) no final do arquivo. Isso ajuda a distingui-lo de outras funções, auxiliares, declaradas no arquivo.
O objeto context permite chamar outras funções de atividade e passar parâmetros de entrada usando o método call_activity. O código chama E1_SayHello três vezes em sequência com valores de parâmetros diferentes, usando yield para indicar que a execução deve aguardar as chamadas de função de atividade assíncrona serem retornadas. O valor retornado de cada chamada é retornado no final da função.
[FunctionName("E1_SayHello")]
public static string SayHello([ActivityTrigger] IDurableActivityContext context)
{
string name = context.GetInput<string>();
return $"Hello {name}!";
}
As atividades usam o atributo ActivityTrigger. Use o atributo IDurableActivityContext fornecido para executar ações relacionadas à atividade, como acessar o valor de entrada usando GetInput<T>.
A implementação de E1_SayHello é uma operação de formatação de cadeia de caracteres relativamente simples.
Em vez de associar a um IDurableActivityContext, você pode associar diretamente ao tipo que é passado para a função de atividade. Por exemplo:
O arquivo function.json da função de atividade E1_SayHello é semelhante ao de E1_HelloSequence, exceto por usar um tipo de associação activityTrigger em vez de um tipo de associação orchestrationTrigger.
Todas as funções de atividade chamadas por uma função de orquestração devem usar a associação activityTrigger.
A implementação de E1_SayHello é uma operação de formatação de cadeia de caracteres relativamente simples.
E1_SayHello/index.js
module.exports = function (context) {
context.done(null, `Hello ${context.bindings.name}!`);
};
Ao contrário de uma função de orquestração, uma função de atividade não precisa de nenhuma configuração especial. A entrada passada a ela pela função do orquestrador está localizada no objeto context.bindings sob o nome da ligação activityTrigger; nesse caso, context.bindings.name. O nome da associação pode ser definido como parâmetro da função exportada e acessado diretamente, que é o que o código de exemplo faz.
A implementação de sayHello é uma operação de formatação de cadeia de caracteres relativamente simples.
Ao contrário de uma função de orquestração, uma função de atividade não precisa de nenhuma configuração especial. A entrada passada para ela pela função do orquestrador é o primeiro argumento da função. O segundo argumento é o contexto da invocação, que não é usado nesse exemplo.
E1_SayHello/function.json
O arquivo function.json da função de atividade E1_SayHello é semelhante ao de E1_HelloSequence, exceto por usar um tipo de associação activityTrigger em vez de um tipo de associação orchestrationTrigger.
Ao contrário de uma função de orquestrador, uma função de atividade não precisa de nenhuma configuração especial. A entrada passada para ela pela função de orquestrador é diretamente acessível como o parâmetro para a função.
Função de cliente HttpStart
Você pode iniciar uma instância da função de orquestrador usando uma função de cliente. Você usará a função HttpStart disparada por HTTP para iniciar instâncias de E1_HelloSequence.
public static class HttpStart
{
[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
[DurableClient] IDurableClient starter,
string functionName,
ILogger log)
{
// Function input comes from the request content.
object eventData = await req.Content.ReadAsAsync<object>();
string instanceId = await starter.StartNewAsync(functionName, eventData);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
Para interagir com orquestradores, a função deve incluir uma associação de entrada DurableClient. Use o cliente para iniciar uma orquestração. Ele também pode ajudar você a retornar uma resposta HTTP contendo URLs para verificar o status da nova orquestração.
Use df.getClient para obter um objeto DurableOrchestrationClient. Use o cliente para iniciar uma orquestração. Ele também pode ajudar você a retornar uma resposta HTTP contendo URLs para verificar o status da nova orquestração.
Para gerenciar e interagir com orquestradores, a função deve incluir uma vinculação de dados de entrada no durableClient. Essa vinculação precisa ser especificada no argumento extraInputs ao registrar a função. Uma entrada no durableClient pode ser obtida chamando o df.input.durableClient().
Use df.getClient para obter um objeto DurableClient. Use o cliente para iniciar uma orquestração. Ele também pode ajudar você a retornar uma resposta HTTP contendo URLs para verificar o status da nova orquestração.
Para interagir com orquestradores, a função deve incluir uma associação de entrada durableClient.
HttpStart/__init__.py
import logging
import azure.functions as func
import azure.durable_functions as df
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
client = df.DurableOrchestrationClient(starter)
instance_id = await client.start_new(req.route_params["functionName"], None, None)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
return client.create_check_status_response(req, instance_id)
Use o construtor DurableOrchestrationClient para obter um Durable Functions cliente. Use o cliente para iniciar uma orquestração. Ele também pode ajudar você a retornar uma resposta HTTP contendo URLs para verificar o status da nova orquestração.
Execute o exemplo
Para executar a orquestração E1_HelloSequence, envie a solicitação HTTP POST para a função HttpStart.
POST http://{host}/orchestrators/E1_HelloSequence
Observação
O snippet de código HTTP anterior pressupõe que exista uma entrada no arquivo host.json que remove o prefixo api/ padrão de todas as URLs de funções de gatilho HTTP. Você pode encontrar a marcação para essa configuração no arquivo host.json nos exemplos.
Por exemplo, se você estiver executando a amostra em um aplicativo da função chamado "myfunctionapp", substitua "{host}" por "myfunctionapp.azurewebsites.net".
O resultado é uma resposta HTTP 202, como esta (resumido para fins de brevidade):
Neste ponto, a orquestração é enfileirada e começa a ser executada imediatamente. A URL no cabeçalho Location pode ser usada para verificar o status da execução.
GET http://{host}/runtime/webhooks/durabletask/instances/96924899c16d43b08a536de376ac786b?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
O resultado é o status da orquestração. Ela é executada e concluída rapidamente e você a verá com estado Concluído, com uma resposta semelhante esta (resumida para fins de brevidade):
Como você pode ver, o runtimeStatus da instância é Concluído e o output contém o resultado serializado em JSON da execução da função de orquestrador.
Observação
Você pode implementar uma lógica inicial semelhante a outros tipos de gatilho, como queueTrigger, eventHubTrigger ou timerTrigger.
Examine os logs de execução da função. A função E1_HelloSequence foi iniciada e concluída várias vezes devido ao comportamento de reprodução descrito no tópico confiabilidade da orquestração. Por outro lado, houve apenas três execuções de E1_SayHello, uma vez que as execuções dessas funções não são repetidas.
Próximas etapas
Este exemplo demonstrou uma orquestração de encadeamento de função simples. O próximo exemplo mostra como implementar o padrão de fan-out/fan-in.