

# Funções duráveis do Lambda
<a name="durable-functions"></a>

As funções duráveis do Lambda permitem que sejam criadas aplicações resilientes de várias etapas e fluxos de trabalho de IA que podem ser executadas por até um ano, mantendo um progresso confiável apesar das interrupções. Quando uma função durável é executada, esse ciclo de vida completo é chamado de execução durável, que usa pontos de verificação para monitorar o progresso e se recuperar automaticamente de falhas por meio de reprodução, reexecutando desde o início e ignorando o trabalho concluído.

Em cada função, você usa operações duráveis como blocos de construção fundamentais. As etapas executam a lógica de negócios com novas tentativas e rastreamento de progresso integrados, enquanto as esperas suspendem a execução sem incorrer em custos de computação, tornando-as ideais para processos de longa execução, como fluxos de trabalho com humanos no loop ou sondagens de dependências externas. Se você estiver processando pedidos, coordenando microsserviços ou orquestrando aplicações de IA agêntica, as funções duráveis mantêm o estado automaticamente e se recuperam de falhas enquanto você escreve código em linguagens de programação familiares.

## Benefícios principais
<a name="durable-functions-benefits"></a>

**Escreva código resiliente naturalmente:** com construções de programação familiares, você escreve código que lida com falhas automaticamente. Pontos de verificação integrados, novas tentativas transparentes e recuperação automática significam que sua lógica de negócios permanece limpa e focada.

**Pague somente pelo que você usar:** durante as operações de espera, sua função é suspensa sem incorrer em cobranças computacionais. Para fluxos de trabalho de longa duração que esperem horas ou dias, você pagará somente pelo tempo real de processamento, e não pela espera ociosa.

**Simplicidade operacional:** com o modelo de tecnologia sem servidor do Lambda, você obtém escalabilidade automática, incluindo escala até zero, sem infraestrutura de gerenciamento. Funções duráveis lidam com gerenciamento de estado, lógica de novas tentativas e recuperação de falhas automaticamente, reduzindo a sobrecarga operacional.

## Quando usar as funções duráveis
<a name="durable-functions-use-cases"></a>

**Coordenação de curta duração:** coordene pagamentos, inventário e envios em vários serviços com reversão automática em caso de falhas. Processe pedidos por meio de validação, autorização de pagamento, alocação de inventário e atendimento com conclusão garantida.

**Processe pagamentos com confiança:** crie fluxos de pagamento resilientes que mantenham o estado da transação em caso de falhas e lidem com novas tentativas automaticamente. Coordene a autorização em várias etapas, as verificações de fraudes e a liquidação entre provedores de pagamento com total auditabilidade em todas as etapas.

**Crie fluxos de trabalho de IA confiáveis:** crie fluxos de trabalho de IA em várias etapas que encadeiem chamadas de modelos, incorporem feedback humano e lidem com tarefas de longa duração de forma determinística durante falhas. Retome a execução automaticamente após a suspensão e pague apenas pelo tempo de execução ativo.

**Organize o atendimento complexo de pedidos:** coordene o processamento de pedidos em sistemas de inventário, pagamento, envio e notificação com resiliência integrada. Lide automaticamente com falhas parciais, preserve o estado do pedido apesar das interrupções e aguarde com eficiência por eventos externos sem consumir recursos computacionais.

**Automatize fluxos de trabalho de negócios em várias etapas:** crie fluxos de trabalho confiáveis para integração de funcionários, aprovações de empréstimos e processos de conformidade que abranjam dias ou semanas. Mantenha o estado do fluxo de trabalho em todas as aprovações humanas, integrações de sistemas e tarefas agendadas, ao mesmo tempo em que fornece visibilidade total do status e do histórico do processo.

### Como as funções duráveis se comparam ao Step Functions
<a name="durable-functions-vs-step-functions"></a>

Tanto as funções duráveis quanto o Step Functions oferecem orquestração de fluxo de trabalho com gerenciamento automático de estados. As principais diferenças são onde eles são executados e como você define os fluxos de trabalho:
+ **Funções duráveis:** executadas no Lambda, usam linguagens de programação padrão, gerenciadas no ambiente Lambda
+ **Step Functions:** serviço independente, DSL baseado em gráficos ou designer visual, totalmente gerenciado sem manutenção

As funções duráveis são ideais para o desenvolvimento de aplicações no Lambda, onde os fluxos de trabalho são fortemente acoplados à lógica de negócios. O Step Functions se destaca na orquestração do fluxo de trabalho entre serviços da AWS em que você precisa de design visual, integrações nativas para mais de 220 serviços e infraestrutura sem manutenção.

Para uma comparação detalhada, consulte [Funções duráveis ou Step Functions](durable-step-functions.md).

## Como funciona
<a name="durable-functions-how-it-works"></a>

 Nos bastidores, as funções duráveis são funções do Lambda regulares que usam um mecanismo de ponto de verificação/reprodução para monitorar o progresso e apoiar operações de longa duração por meio de pontos de suspensão definidos pelo usuário, comumente chamados de execução durável. Depois que sua função é retomada após uma pausa ou interrupção, o sistema executa a reprodução. Durante a reprodução, seu código é executado desde o início, mas ignora os pontos de verificação concluídos, usando os resultados armazenados em vez de reexecutar as operações concluídas. Esse mecanismo de reprodução garante consistência e permite execuções de longa duração.

Para aproveitar esse mecanismo de ponto de verificação e reprodução em suas aplicações, o Lambda fornece um SDK de execução durável. O SDK elimina a complexidade do gerenciamento de pontos de verificação e reprodução, expondo primitivas simples chamadas operações duráveis que você usa em seu código. O SDK está disponível para JavaScript, TypeScript, Python e Java (versão prévia), integrando-se perfeitamente ao seu fluxo de trabalho de desenvolvimento do Lambda já existente.

Com o SDK, você empacota seu manipulador de eventos do Lambda, que então fornece um DurableContext junto ao seu evento. Esse contexto dá acesso a operações duráveis, como etapas e esperas. Você escreve a lógica da sua função como um código sequencial normal, mas, em vez de chamar serviços diretamente, agrupa essas chamadas em etapas para verificação automática e novas tentativas. Quando é necessário pausar a execução, você adiciona esperas que suspendem sua função sem incorrer em cobranças. O SDK lida com toda a complexidade do gerenciamento de estados e da reprodução nos bastidores, para que seu código permaneça limpo e legível.

 ![\[Filter for Amazon Inspector results related to Lambda functions\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/how_durable_works.png) 

## Próximas etapas
<a name="durable-functions-next-steps"></a>
+ [Conceitos básicos das funções duráveis](durable-getting-started.md)
+ [Explore o SDK de execução durável](durable-execution-sdk.md)
+ [Funções duráveis ou Step Functions](durable-step-functions.md)
+ [Monitore e depure as funções duráveis](durable-monitoring.md)
+ [Verifique a segurança e as permissões](durable-security.md)
+ [Siga as práticas recomendadas](durable-best-practices.md)

# Conceitos básicos
<a name="durable-basic-concepts"></a>

O Lambda fornece SDKs de execução durável para JavaScript, TypeScript e Python. Esses SDKs são a base para a criação de funções duráveis, fornecendo as primitivas de que você precisa para pontos de verificação de progresso, lidar com novas tentativas e gerenciar o fluxo de execução. Para obter exemplos e documentação completa do SDK, consulte o [SDK do Javascript/TypeScript](https://github.com/aws/aws-durable-execution-sdk-js) e o [SDK do Python](https://github.com/aws/aws-durable-execution-sdk-python) no GitHub.

## Execução durável
<a name="durable-execution-concept"></a>

Uma **execução durável** representa o ciclo de vida completo de uma função durável do Lambda, usando um mecanismo de ponto de verificação e reprodução para acompanhar o progresso da lógica de negócios, suspender a execução e recuperar as falhas. Quando as funções são retomadas após suspensões ou interrupções, os pontos de verificação concluídos anteriormente são repetidos e a função continua em execução.

O ciclo de vida pode incluir várias invocações de uma função do Lambda para concluir a execução, especialmente após suspensões ou recuperação de falhas. Essa abordagem permite que sua função funcione por longos períodos (até um ano), mantendo um progresso confiável apesar das interrupções.

**Como a reprodução funciona**  
O Lambda mantém um log em execução de todas as operações duráveis (etapas, esperas e outras operações) à medida que sua função é executada. Quando sua função precisa fazer uma pausa ou encontra uma interrupção, o Lambda salva esse log de ponto de verificação e interrompe a execução. Quando chega a hora de retomar, o Lambda invoca sua função novamente desde o início e reproduz o log do ponto de verificação, substituindo os valores armazenados pelas operações concluídas. Isso significa que seu código é executado novamente, mas as etapas concluídas anteriormente não são reexecutadas. Seus resultados armazenados são usados em vez disso.

Esse mecanismo de reprodução é fundamental para entender as funções duráveis. Seu código deve ser determinístico durante a reprodução, o que significa que ele produz os mesmos resultados com as mesmas entradas. Evite operações com efeitos colaterais (como a geração de números aleatórios ou a obtenção da hora atual) fora das etapas, pois elas podem produzir valores diferentes durante a reprodução e causar um comportamento não determinístico.

## DurableContext
<a name="durable-context-concept"></a>

**DurableContext** é o objeto de contexto que sua função durável recebe. Ele fornece métodos para operações duráveis, como etapas e esperas, que criam pontos de verificação e gerenciam o fluxo de execução.

Sua função durável recebe um `DurableContext` em vez do contexto do Lambda padrão:

------
#### [ TypeScript ]

```
import {
  DurableContext,
  withDurableExecution,
} from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const result = await context.step(async () => {
      return "step completed";
    });
    return result;
  },
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import (
    DurableContext,
    durable_execution,
    durable_step,
)

@durable_step
def my_step(step_context, data):
    # Your business logic
    return result

@durable_execution
def handler(event, context: DurableContext):
    result = context.step(my_step(event["data"]))
    return result
```

------

O SDK do Python para funções duráveis usa métodos síncronos e não oferece suporte a `await`. O SDK do TypeScript usa `async/await`.

## Etapas
<a name="steps-concept"></a>

O **Steps** executa a lógica de negócios com novas tentativas integradas e pontos de verificação automáticos. Cada etapa salva seu resultado, garantindo que sua função possa ser retomada a partir de qualquer etapa concluída após interrupções.

------
#### [ TypeScript ]

```
// Each step is automatically checkpointed
const order = await context.step(async () => processOrder(event));
const payment = await context.step(async () => processPayment(order));
const result = await context.step(async () => completeOrder(payment));
```

------
#### [ Python ]

```
# Each step is automatically checkpointed
order = context.step(lambda: process_order(event))
payment = context.step(lambda: process_payment(order))
result = context.step(lambda: complete_order(payment))
```

------

## Estados de espera
<a name="wait-states-concept"></a>

Os **estados de espera** são pausas planejadas em que sua função para de funcionar (e para de carregar) até a hora de continuar. Use-os para aguardar períodos de tempo, retornos de chamada externos ou condições específicas.

------
#### [ TypeScript ]

```
// Wait for 1 hour without consuming resources
await context.wait({ seconds:3600 });

// Wait for external callback
const approval = await context.waitForCallback(
  async (callbackId) => sendApprovalRequest(callbackId)
);
```

------
#### [ Python ]

```
# Wait for 1 hour without consuming resources
context.wait(3600)

# Wait for external callback
approval = context.wait_for_callback(
    lambda callback_id: send_approval_request(callback_id)
)
```

------

Quando sua função encontra uma espera ou precisa fazer uma pausa, o Lambda salva esse log de ponto de verificação e interrompe a execução. Quando chega a hora de retomar, o Lambda invoca sua função novamente e reproduz o log do ponto de verificação, substituindo os valores armazenados pelas operações concluídas.

Para fluxos de trabalho mais complexos, as funções do Lambda duráveis também vêm com operações avançadas como `parallel()` para execução simultânea, `map()` para o processamento de matrizes, `runInChildContext()` para operações aninhadas e `waitForCondition()` para sondagem. Consulte [Exemplos](durable-examples.md) para obter exemplos detalhados e orientações sobre quando usar cada operação.

## Invocação de outras funções
<a name="invoke-concept"></a>

**Invoke** permite que uma função durável chame outras funções do Lambda e aguarde por seus resultados. A função de chamada é suspensa enquanto a função invocada é executada, criando um ponto de verificação que preserva o resultado. Isso permite que você crie fluxos de trabalho modulares em que funções especializadas tratam tarefas específicas.

Use `context.invoke()` para chamar outras funções de dentro de sua função durável. A invocação é marcada com ponto de verificação, portanto, se sua função for interrompida após a conclusão da função invocada, ela será retomada com o resultado armazenado sem invocar novamente a função.

------
#### [ TypeScript ]

```
// Invoke another function and wait for result
const customerData = await context.invoke(
  'validate-customer',
  'arn:aws:lambda:us-east-1:123456789012:function:customer-service:1',
  { customerId: event.customerId }
);

// Use the result in subsequent steps
const order = await context.step(async () => {
  return processOrder(customerData);
});
```

------
#### [ Python ]

```
# Invoke another function and wait for result
customer_data = context.invoke(
    'arn:aws:lambda:us-east-1:123456789012:function:customer-service:1',
    {'customerId': event['customerId']},
    name='validate-customer'
)

# Use the result in subsequent steps
order = context.step(
    lambda: process_order(customer_data),
    name='process-order'
)
```

------

A função invocada pode ser uma função do Lambda durável ou padrão. Se você invocar uma função durável, a função de chamada aguardará a conclusão da execução durável completa. Esse padrão é comum em arquiteturas de microsserviços em que cada função manipula um domínio específico, permitindo que você componha fluxos de trabalho complexos a partir de funções especializadas e reutilizáveis.

**nota**  
Não há suporte a invocações entre contas. A função invocada deve estar na mesma conta da AWS da função de chamada.

## Configuração de função durável
<a name="durable-configuration-basic"></a>

As funções duráveis têm configurações específicas que controlam o comportamento de execução e a retenção de dados. Essas configurações são separadas da configuração padrão da função do Lambda e se aplicam a todo o ciclo de vida de execução durável.

O objeto **DurableConfig** define a configuração para as funções duráveis:

```
{
  "ExecutionTimeout": Integer,
  "RetentionPeriodInDays": Integer
}
```

### Execution timeout (Tempo limite de execução)
<a name="durable-execution-timeout"></a>

O **tempo limite de execução** controla por quanto tempo uma execução durável pode ser executada do início à conclusão. Isso é diferente do tempo limite da função do Lambda, que controla por quanto tempo uma única invocação de função pode ser executada.

Uma execução durável pode abranger várias invocações de função do Lambda à medida que avança nos pontos de verificação, esperas e repetições. O tempo limite de execução se aplica ao tempo total decorrido da execução durável, não às invocações de funções individuais.

**Como compreender as diferenças**  
O tempo limite da função do Lambda (máximo de 15 minutos) limita cada invocação individual de sua função. O tempo limite de execução durável (máximo de 1 ano) limita o tempo total desde o início da execução até sua conclusão, falha ou tempo limite. Durante esse período, sua função pode ser invocada várias vezes enquanto processa etapas, espera e se recupera de falhas.

Por exemplo, se você definir um tempo limite de execução durável de 24 horas e um tempo limite da função do Lambda de 5 minutos:
+ Cada invocação de função deve ser concluída em 5 minutos
+ Toda a execução durável pode ser executada por até 24 horas
+ Sua função pode ser invocada várias vezes durante essas 24 horas
+ As operações de espera não contam para o tempo limite da função do Lambda, mas contam para o tempo limite de execução

É possível configurar o tempo limite de execução ao criar uma função durável usando o console do Lambda, a AWS CLI ou o AWS SAM. No console do Lambda, escolha sua função e, em seguida, Configuração, Execução durável. Defina o valor do tempo limite de execução em segundos (padrão: 86400 segundos/24 horas, mínimo: 60 segundos, máximo: 31536000 segundos/ 1 ano).

**nota**  
O tempo limite de execução e o tempo limite da função do Lambda são configurações diferentes. O tempo limite da função do Lambda controla por quanto tempo cada invocação individual pode ser executada (máximo de 15 minutos). O tempo limite de execução controla o tempo total decorrido para toda a execução durável (máximo de 1 ano).

### Período de retenção
<a name="durable-retention-period"></a>

O **período de retenção** controla por quanto tempo o Lambda retém o histórico de execução e os dados do ponto de verificação após a conclusão de uma execução durável. Esses dados incluem resultados da etapa, estado de execução e o log completo dos pontos de verificação.

Depois que o período de retenção expira, o Lambda exclui o histórico de execução e os dados do ponto de verificação. Não será possível mais recuperar os detalhes da execução nem repetir a execução. O período de retenção começa quando a execução atinge um estado terminal (SUCCEEDED, FAILED, STOPPED ou TIMED\$1OUT).

É possível configurar o período de retenção ao criar uma função durável usando o console do Lambda, a AWS CLI ou o AWS SAM. No console do Lambda, escolha sua função e, em seguida, Configuração, Execução durável. Defina o valor do período de retenção em dias (padrão: 14 dias, mínimo: 1 dia, máximo: 90 dias).

Escolha um período de retenção com base em seus requisitos de conformidade, necessidades de depuração e considerações de custo. Períodos de retenção mais longos fornecem mais tempo para depuração e auditoria, mas aumentam os custos de armazenamento.

## Consulte também
<a name="durable-basic-concepts-see-also"></a>
+ [Funções duráveis ou Step Functions](durable-step-functions.md): compare funções duráveis com o Step Functions para entender quando cada abordagem é mais eficaz.

# Criação de funções duráveis do Lambda
<a name="durable-getting-started"></a>

Para começar a usar as funções duráveis do Lambda, use o console do Lambda para criar uma função durável. Em alguns minutos, é possível criar e implantar uma função durável que use etapas e esperas para demonstrar a execução baseada em pontos de verificação.

Ao prosseguir no tutorial, você aprenderá conceitos fundamentais de funções duráveis, como usar o objeto `DurableContext`, criar pontos de verificação com etapas e pausar a execução com esperas. Você também aprenderá como a reprodução funciona quando sua função é retomada após uma espera.

Para simplificar, este tutorial mostra como criar sua função usando o runtime do Python ou do Node.js. Com essas linguagens interpretadas, você pode editar o código da função diretamente no editor de código integrado do console.

Atualmente, as funções duráveis em Java (Pré-visualização) só podem ser realizadas por meio de imagens de contêiner. Para obter mais informações sobre como criar funções duráveis a partir de imagens de contêiner, consulte [Runtimes compatíveis com funções duráveis](durable-supported-runtimes.md) ou [Implantar funções duráveis do Lambda com Infraestrutura como Código](durable-getting-started-iac.md).

**nota**  
Atualmente, as funções duráveis oferecem suporte a runtimes de Python e Node.js (JavaScript/TypeScript) e imagens de contêiner (OCI), como Java. Para obter uma lista completa das versões de runtime e opções de imagem de contêiner compatíveis, consulte [Runtimes compatíveis para funções duráveis](durable-supported-runtimes.md). Para obter mais informações sobre como usar imagens de contêiner com o Lambda, consulte [Criação de imagens de contêiner do Lambda](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) no Guia do desenvolvedor do Lambda.

**dica**  
Para saber como construir **soluções com tecnologia sem servidor**, confira o [Guia do desenvolvedor com tecnologia sem servidor](https://docs.aws.amazon.com/serverless/latest/devguide/).

## Pré-requisitos
<a name="durable-getting-started-prerequisites"></a>

### Inscrever-se para uma Conta da AWS
<a name="sign-up-for-aws"></a>

Se você ainda não tem uma Conta da AWS, siga as etapas abaixo para criar uma.

**Como cadastrar uma Conta da AWS**

1. Abra [https://portal.aws.amazon.com/billing/signup](https://portal.aws.amazon.com/billing/signup).

1. Siga as instruções online.

   Parte do procedimento de inscrição envolve receber uma chamada telefônica ou uma mensagem de texto e inserir um código de verificação pelo teclado do telefone.

   Quando você se inscreve para uma Conta da AWS, um *Usuário raiz da conta da AWS* é criado. O usuário-raiz tem acesso a todos os Serviços da AWS e recursos na conta. Como prática recomendada de segurança, atribua o acesso administrativo a um usuário e use somente o usuário-raiz para executar [tarefas que exigem acesso de usuário-raiz](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks).

A AWS envia um e-mail de confirmação depois que o processo de inscrição é concluído. A qualquer momento, é possível exibir as atividades da conta atual e gerenciar sua conta acessando [https://aws.amazon.com/](https://aws.amazon.com/) e selecionando **Minha conta**.

### Criar um usuário com acesso administrativo
<a name="create-an-admin"></a>

Depois de se cadastrar em uma Conta da AWS, proteja seu Usuário raiz da conta da AWS, habilite o Centro de Identidade do AWS IAM e crie um usuário administrativo para não usar o usuário-raiz em tarefas cotidianas.

**Proteger o Usuário raiz da conta da AWS**

1.  Faça login no [Console de gerenciamento da AWS](https://console.aws.amazon.com/) como o proprietário da conta ao escolher a opção **Usuário-raiz** e inserir o endereço de e-mail da Conta da AWS. Na próxima página, insira a senha.

   Para obter ajuda ao fazer login usando o usuário-raiz, consulte [Fazer login como usuário-raiz](https://docs.aws.amazon.com/signin/latest/userguide/console-sign-in-tutorials.html#introduction-to-root-user-sign-in-tutorial) no *Guia do usuário do Início de Sessão da AWS*.

1. Habilite a autenticação multifator (MFA) para o usuário-raiz.

   Para obter instruções, consulte [Habilitar um dispositivo MFA virtual para sua Conta da AWS de usuário-raiz (console)](https://docs.aws.amazon.com/IAM/latest/UserGuide/enable-virt-mfa-for-root.html) no *Guia do usuário do IAM*.

**Criar um usuário com acesso administrativo**

1. Habilita o Centro de Identidade do IAM.

   Para obter instruções, consulte [Habilitar o Centro de Identidade do AWS IAM](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-set-up-for-idc.html) no *Guia do usuário do Centro de Identidade do AWS IAM*.

1. No Centro de Identidade do IAM, conceda o acesso administrativo a um usuário.

   Para obter um tutorial sobre como usar o Diretório do Centro de Identidade do IAM como a fonte de identidade, consulte [Configurar o acesso dos usuários com o Diretório do Centro de Identidade do IAM padrão](https://docs.aws.amazon.com//singlesignon/latest/userguide/quick-start-default-idc.html) no *Guia do usuário do Centro de Identidade do AWS IAM*.

**Iniciar sessão como o usuário com acesso administrativo**
+ Para fazer login com o seu usuário do Centro de Identidade do IAM, use o URL de login enviado ao seu endereço de e-mail quando o usuário do Centro de Identidade do IAM foi criado.

  Para obter ajuda para fazer login usando um usuário do Centro de Identidade do IAM, consulte [Fazer login no portal de acesso da AWS](https://docs.aws.amazon.com/signin/latest/userguide/iam-id-center-sign-in-tutorial.html), no *Guia do usuário do Início de Sessão da AWS*.

**Atribuir acesso a usuários adicionais**

1. No Centro de Identidade do IAM, crie um conjunto de permissões que siga as práticas recomendadas de aplicação de permissões com privilégio mínimo.

   Para obter instruções, consulte [Criar um conjunto de permissões](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-started-create-a-permission-set.html) no *Guia do usuário do Centro de Identidade do AWS IAM*.

1. Atribua usuários a um grupo e, em seguida, atribua o acesso de logon único ao grupo.

   Para obter instruções, consulte [Adicionar grupos](https://docs.aws.amazon.com//singlesignon/latest/userguide/addgroups.html) no *Guia do usuário do Centro de Identidade do AWS IAM*.

## Criação de uma função durável do Lambda com o console
<a name="getting-started-create-durable-function"></a>

Neste exemplo, sua função durável processa um pedido por meio de várias etapas com verificação automática. A função usa um objeto JSON contendo um ID do pedido, valida o pedido, processa o pagamento e confirma o pedido. Cada etapa é verificada automaticamente, portanto, se a função for interrompida, ela será retomada a partir da última etapa concluída.

Sua função também demonstra uma operação de espera, pausando a execução por um curto período para simular a espera pela confirmação externa.

**Para criar uma função durável com o console**

1. Abra a [página Funções](https://console.aws.amazon.com/lambda/home#/functions) do console do Lambda.

1. Selecione **Criar função**.

1. Selecione **Criar do zero**.

1. No painel **Informações básicas**, para **Nome da função**, insira `myDurableFunction`.

1. Em **Runtime**, escolha **Node.js 24** ou **Python 3.14**.

1. Selecione **Habilitar execução durável**.

O Lambda cria sua função durável com um [perfil de execução](lambda-intro-execution-role.md) que inclui permissões para operações de ponto de verificação (`lambda:CheckpointDurableExecutions` e `lambda:GetDurableExecutionState`).

**nota**  
Os runtimes do Lambda incluem o SDK de execução durável, para que seja possível testar funções duráveis sem dependências de empacotamento. No entanto, recomendamos incluir o SDK em seu pacote de implantação para produção. Isso garante a consistência da versão e evita possíveis atualizações de runtime que possam afetar sua função.

Use o editor de código embutido do console para adicionar o código da sua função durável.

------
#### [ Node.js ]

**Modificar o código no console**

1. Escolha a guia **Código**.

   No editor de código integrado do console, você deve ver o código da função que o Lambda criou. Se você não vir a guia **index.mjs** no editor de código, selecione **index.mjs** no explorador de arquivos, conforme mostrado no diagrama a seguir.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/durable-nodejs.png)

1. Cole o código a seguir na guia **index.mjs**, substituindo o código que o Lambda criou.

   ```
   import {
     DurableContext,
     withDurableExecution,
   } from "@aws/durable-execution-sdk-js";
   
   export const handler = withDurableExecution(
     async (event, context) => {
       const orderId = event.orderId;
       
       // Step 1: Validate order
       const validationResult = await context.step(async (stepContext) => {
         stepContext.logger.info(`Validating order ${orderId}`);
         return { orderId, status: "validated" };
       });
       
       // Step 2: Process payment
       const paymentResult = await context.step(async (stepContext) => {
         stepContext.logger.info(`Processing payment for order ${orderId}`);
         return { orderId, status: "paid", amount: 99.99 };
       });
       
       // Wait for 10 seconds to simulate external confirmation
       await context.wait({ seconds: 10 });
       
       // Step 3: Confirm order
       const confirmationResult = await context.step(async (stepContext) => {
         stepContext.logger.info(`Confirming order ${orderId}`);
         return { orderId, status: "confirmed" };
       });
           
       return {
         orderId: orderId,
         status: "completed",
         steps: [validationResult, paymentResult, confirmationResult]
       };
     }
   );
   ```

1. Na seção **DEPLOY**, escolha **Implantar** para atualizar o código da função:  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**Noções básicas sobre o seu código de função durável**  
Antes de passar para a próxima etapa, vamos analisar o código da função e compreender alguns conceitos-chave das funções duráveis.
+ O wrapper `withDurableExecution`:

  Sua função durável é encapsulada com `withDurableExecution`. Esse encapsulamento permite uma execução durável fornecendo o objeto `DurableContext` e gerenciando as operações de ponto de verificação.
+ O objeto `DurableContext`:

  Em vez do contexto padrão do Lambda, sua função recebe um `DurableContext`. Esse objeto fornece métodos para operações duráveis, como `step()` e `wait()`, que criam os pontos de verificação.
+ Etapas e pontos de verificação:

  Cada chamada a `context.step()` cria um ponto de verificação antes e depois da execução. Se sua função for interrompida, ela será retomada a partir do último ponto de verificação concluído. A função não executa novamente as etapas concluídas. Em vez disso, ele usa os resultados armazenados.
+ Operações de espera:

  A chamada a `context.wait()` pausa a execução sem consumir recursos computacionais. Quando espera é concluída, o Lambda invoca sua função novamente e reproduz o log do ponto de verificação, substituindo os valores armazenados por etapas concluídas.
+ Mecanismo de reprodução:

  Quando sua função é retomada após uma espera ou interrupção, o Lambda executa seu código desde o início. Contudo, as etapas concluídas não são reexecutadas. O Lambda reproduz seus resultados a partir do log do ponto de verificação. É por isso que seu código deve ser determinístico.

------
#### [ Python ]

**Modificar o código no console**

1. Escolha a guia **Código**.

   No editor de código integrado do console, você deve ver o código da função que o Lambda criou. Se você não vir a guia **lambda\$1function.py** no editor de código, selecione **lambda\$1function.py** no explorador de arquivos, conforme mostrado no diagrama a seguir.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/durable-python.png)

1. Cole o código a seguir na guia **lambda\$1function.py**, substituindo o código que o Lambda criou.

   ```
   from aws_durable_execution_sdk_python import (
       DurableContext,
       durable_execution,
       durable_step,
   )
   from aws_durable_execution_sdk_python.config import Duration
   
   @durable_step
   def validate_order(step_context, order_id):
       step_context.logger.info(f"Validating order {order_id}")
       return {"orderId": order_id, "status": "validated"}
   
   @durable_step
   def process_payment(step_context, order_id):
       step_context.logger.info(f"Processing payment for order {order_id}")
       return {"orderId": order_id, "status": "paid", "amount": 99.99}
   
   @durable_step
   def confirm_order(step_context, order_id):
       step_context.logger.info(f"Confirming order {order_id}")
       return {"orderId": order_id, "status": "confirmed"}
   
   @durable_execution
   def lambda_handler(event, context: DurableContext):
       order_id = event['orderId']
       
       # Step 1: Validate order
       validation_result = context.step(validate_order(order_id))
       
       # Step 2: Process payment
       payment_result = context.step(process_payment(order_id))
       
       # Wait for 10 seconds to simulate external confirmation
       context.wait(Duration.from_seconds(10))
       
       # Step 3: Confirm order
       confirmation_result = context.step(confirm_order(order_id))
           
       return {
           "orderId": order_id,
           "status": "completed",
           "steps": [validation_result, payment_result, confirmation_result]
       }
   ```

1. Na seção **DEPLOY**, escolha **Implantar** para atualizar o código da função:  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

**Noções básicas sobre o seu código de função durável**  
Antes de passar para a próxima etapa, vamos analisar o código da função e compreender alguns conceitos-chave das funções duráveis.
+ O decorator `@durable_execution`:

  Sua função de manipulador é decorada com `@durable_execution`. Esse decorador permite uma execução durável fornecendo o objeto `DurableContext` e gerenciando as operações de ponto de verificação.
+ O decorator `@durable_step`:

  Cada função de etapa é decorada com `@durable_step`. Esse decorador marca a função como uma etapa durável que cria pontos de verificação.
+ O objeto `DurableContext`:

  Em vez do contexto padrão do Lambda, sua função recebe um `DurableContext`. Esse objeto fornece métodos para operações duráveis, como `step()` e `wait()`, que criam os pontos de verificação.
+ Etapas e pontos de verificação:

  Cada chamada a `context.step()` cria um ponto de verificação antes e depois da execução. Se sua função for interrompida, ela será retomada a partir do último ponto de verificação concluído. A função não executa novamente as etapas concluídas. Em vez disso, ele usa os resultados armazenados.
+ Operações de espera:

  A chamada a `context.wait()` pausa a execução sem consumir recursos computacionais. Quando espera é concluída, o Lambda invoca sua função novamente e reproduz o log do ponto de verificação, substituindo os valores armazenados por etapas concluídas.
+ O SDK do Python é síncrono:

  Observe que o SDK do Python não usa `await`. Todas as operações duráveis são chamadas de métodos síncronas.

------

## Invocação da função durável usando o editor de códigos do console
<a name="get-started-invoke-durable-manually"></a>

Quando nenhuma versão explícita é especificada (ou publicada), o console invoca a função durável usando o qualificador de versão `$LATEST`. No entanto, para a execução determinística do seu código, você deve sempre usar um ARN qualificado apontando para uma versão estável.

**Para publicar uma versão da sua função**

1. Escolha a guia **Versões**.

1. Escolha **Publicar nova versão**.

1. Em **Descrição da versão**, insira **Initial version** (opcional).

1. Selecione **Publish**.

1. O Lambda criará a versão 1 da sua função. Observe que a função do ARN agora inclui `:1` no final, indicando que esta é a versão 1.

Agora, crie um evento de teste para enviar à sua função. O evento é um documento em formato JSON contendo um ID de pedido.

**Criar o evento de teste**

1. Na seção **TEST EVENTS** do editor de código do console, escolha **Criar evento de teste**.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/getting-started-tutorial/test-event.png)

1. Em **Event Name (Nome do evento)**, insira **myTestEvent**.

1. Na seção **JSON do evento**, substitua o JSON padrão pelo seguinte:

   ```
   {
     "orderId": "order-12345"
   }
   ```

1. Escolha **Salvar**.

**Para testar sua função durável e visualizar a execução**

Na seção **TEST EVENTS** do editor de código do console, selecione o ícone de execução ao lado do evento de teste:

![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/getting-started-tutorial/run-test-event.png)


Sua função durável começará a ser executada. Como ela inclui uma espera de 10 segundos, a invocação inicial é concluída rapidamente e a função será retomada após o período de espera. É possível visualizar o andamento da execução na guia **Execuções duráveis**.

**Para visualizar sua execução da sua função durável**

1. Escolha a guia **Execuções duráveis**.

1. Encontre sua execução na lista. A execução mostra o status atual (Em execução, Com êxito ou Com falha).

1. Escolha o ID da execução para visualizar os detalhes, incluindo:
   + Cronograma de execução, mostrando quando cada etapa foi concluída
   + Histórico dos pontos de verificação
   + Períodos de espera
   + Resultados de etapas

Também é possível visualizar os logs da sua função no CloudWatch Logs para ver a saída do console de cada etapa.

**Para visualizar os registros de invocação da sua função no CloudWatch Logs**

1. Abra a [página Log groups](https://console.aws.amazon.com/cloudwatch/home#logs:) (Grupos de log) do console do CloudWatch.

1. Escolha o nome do grupo de logs para sua função (`/aws/lambda/myDurableFunction`).

1. Role para baixo e selecione o **Fluxo de logs** para as invocações da função que você deseja verificar.  
![\[\]](http://docs.aws.amazon.com/pt_br/lambda/latest/dg/images/log-stream.png)

   Você verá as entradas de log para cada invocação de sua função, incluindo a execução inicial e a reprodução após a espera.

**nota**  
Ao usar o registrador de `DurableContext` (como `context.logger` ou `stepContext.logger`), os registros também aparecem na execução durável e nas visualizações de etapas no console do Lambda. Esses registros podem demorar um pouco para serem carregados.

## Limpeza
<a name="gettingstarted-durable-cleanup"></a>

Quando você tiver terminado de trabalhar com a função durável de exemplo, exclua-a. Também é possível excluir o grupo de logs que armazena os logs da função e a [função de execução](lambda-intro-execution-role.md) que o console criou.

**Como excluir a função do Lambda**

1. Abra a página [Functions](https://console.aws.amazon.com/lambda/home#/functions) (Funções) no console do Lambda.

1. Selecione a função que você criou.

1. Selecione **Ações**, **Excluir**.

1. Digite **confirm** no campo de entrada de texto e escolha **Delete** (Excluir).

**Para excluir o grupo de logs**

1. Abra a [página Log groups](https://console.aws.amazon.com/cloudwatch/home#logs:) (Grupos de log) do console do CloudWatch.

1. Selecione o grupo de logs da função (`/aws/lambda/myDurableFunction`).

1. Selecione **Actions (Ações)**, **Delete log group(s) (Excluir grupo(s) de log)**.

1. Na caixa de diálogo **Delete log group(s)** (Excluir grupo(s) de logs), escolha **Delete** (Excluir).

**Para excluir a função de execução**

1. Abra a [página Roles](https://console.aws.amazon.com/iam/home?#/roles) (Funções) no console do AWS Identity and Access Management (IAM).

1. Selecione o perfil de execução da função (por exemplo, `myDurableFunction-role-31exxmpl`).

1. Escolha **Excluir**.

1. Na caixa de diálogo **Excluir perfil**, insira o nome do perfil e, em seguida, escolha **Excluir**.

## Recursos adicionais e próximas etapas
<a name="durable-getting-started-more-resources"></a>

Agora que você criou e testou uma função durável simples usando o console, siga estes próximos passos:
+ Saiba mais sobre casos de uso comuns para funções duráveis, incluindo transações distribuídas, processamento de pedidos e fluxos de trabalho de revisão humana. Veja [Exemplos](durable-examples.md).
+ Entenda como monitorar execuções de funções duráveis com as métricas e o histórico de execução do CloudWatch. Consulte [Monitoramento e depuração](durable-monitoring.md).
+ Saiba mais sobre como invocar funções duráveis de forma síncrona e assíncrona e gerenciar execuções de longa duração. Consulte [Invocação de funções duráveis](durable-invoking.md).
+ Siga as práticas recomendadas para escrever código determinístico, gerenciar tamanhos de pontos de verificação e otimizar custos. Consulte as [Práticas recomendadas](durable-best-practices.md).
+ Saiba mais sobre como testar as funções duráveis localmente e na nuvem Consulte [Testes de funções duráveis](durable-testing.md).
+ Compare funções duráveis com o Step Functions para entender quando cada abordagem é mais eficaz. Consulte [Funções duráveis ou Step Functions](durable-step-functions.md).

# Implemente e invoque funções duráveis do Lambda com a AWS CLI
<a name="durable-getting-started-cli"></a>

Use a AWS CLI para criar e implantar funções duráveis do Lambda com comandos imperativos. Essa abordagem oferece controle direto sobre cada etapa do processo de implantação.

## Pré-requisitos
<a name="durable-cli-prerequisites"></a>
+ Instale e configure a . AWS CLI. Para obter instruções, consulte [Instalação da AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).
+ Crie um pacote de implantação com o código de função e o SDK de execução durável.
+ Crie um perfil de execução no IAM com a permissões para pontos de verificação.

## Criar a função de execução
<a name="durable-cli-create-role"></a>

Crie um perfil do IAM com permissões para operações básicas de execução e ponto de verificação do Lambda.

**Para criar a função de execução**

1. Crie um documento de política de confiança que permita que o Lambda assuma o perfil. Salve-o como `trust-policy.json`:

   ```
   {
     "Version": "2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": "lambda.amazonaws.com"
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

1. Crie a função:

   ```
   aws iam create-role \
     --role-name durable-function-role \
     --assume-role-policy-document file://trust-policy.json
   ```

1. Anexe a política de execução durável para operações de ponto de verificação e execução básica:

   ```
   aws iam attach-role-policy \
     --role-name durable-function-role \
     --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy
   ```

A política gerenciada `AWSLambdaBasicDurableExecutionRolePolicy` inclui as permissões necessárias para operações de ponto de verificação (`lambda:CheckpointDurableExecutions` e `lambda:GetDurableExecutionState`) e execução básica do Lambda.

## Criação da função durável
<a name="durable-cli-create-function"></a>

Crie sua função durável com o parâmetro `--durable-config`.

**Para criar uma função durável**

1. Empacote seu código de função com as dependências em um arquivo .zip:

   ```
   zip -r function.zip index.mjs node_modules/
   ```

1. Crie a função com a execução durável habilitada:

   ```
   aws lambda create-function \
     --function-name myDurableFunction \
     --runtime nodejs22.x \
     --role arn:aws:iam::123456789012:role/durable-function-role \
     --handler index.handler \
     --zip-file fileb://function.zip \
     --durable-config '{"ExecutionTimeout": 3600, "RetentionPeriodInDays": 7}'
   ```

**nota**  
Você só pode habilitar a execução durável ao criar a função. Não é possível habilitá-la em funções existentes.

**nota**  
Atualmente, funções duráveis em Java (Pré-visualização) só podem ser criadas por meio de imagens de contêiner. Para obter mais informações sobre como criar funções duráveis a partir de imagens de contêiner, consulte [Runtimes compatíveis para funções duráveis](durable-supported-runtimes.md).

## Publicação de uma versão
<a name="durable-cli-publish-version"></a>

Embora as funções duráveis possam ser invocadas usando o qualificador de versão `$LATEST`, você sempre deve usar um ARN qualificado apontando para uma versão estável a fim de garantir a execução determinística do seu código.

```
aws lambda publish-version \
  --function-name myDurableFunction \
  --description "Initial version"
```

O comando retorna o ARN da versão. Anote o número da versão (por exemplo, `:1`) no final do ARN.

Opcionalmente, crie um alias que aponte para a versão.

```
aws lambda create-alias \
  --function-name myDurableFunction \
  --name prod \
  --function-version 1
```

## Invocação da função durável
<a name="durable-cli-invoke"></a>

Invoque sua função durável usando o ARN qualificado (versão ou alias).

**nota**  
**Invocações idempotentes:** para evitar execuções duplicadas ao tentar novamente invocações com falha, você pode especificar um nome de execução que garanta uma semântica de execução única. Consulte [Idempotência](durable-execution-idempotency.md) para obter detalhes.

**Invocação síncrona**  
Para execuções concluídas dentro de 15 minutos, use a invocação síncrona:

```
aws lambda invoke \
  --function-name myDurableFunction:1 \
  --payload '{"orderId": "order-12345"}' \
  --cli-binary-format raw-in-base64-out \
  response.json
```

Ou usando um alias:

```
aws lambda invoke \
  --function-name myDurableFunction:prod \
  --payload '{"orderId": "order-12345"}' \
  --cli-binary-format raw-in-base64-out \
  response.json
```

**Invocação assíncrona**  
Para execuções de longa duração, use a invocação assíncrona:

```
aws lambda invoke \
  --function-name myDurableFunction:prod \
  --invocation-type Event \
  --payload '{"orderId": "order-12345"}' \
  --cli-binary-format raw-in-base64-out \
  response.json
```

Com a invocação assíncrona, o Lambda retorna imediatamente. A função continua em execução em segundo plano.

**nota**  
Você pode usar `$LATEST` para prototipagem e testes no console. Para workloads de produção, use uma versão publicada ou um alias.

## Gerenciamento de execuções duráveis
<a name="durable-cli-manage-executions"></a>

Use os comandos a seguir para gerenciar e monitorar execuções de funções duráveis

**Execuções de lista**  
Liste todas as execuções de uma função durável:

```
aws lambda list-durable-executions-by-function \
  --function-name myDurableFunction
```

**Obtenção dos detalhes da execução**  
Obtenha detalhes sobre uma execução específica:

```
aws lambda get-durable-execution \
  --durable-execution-arn arn:aws:lambda:us-east-1:123456789012:function:myDurableFunction:my-function-version/durable-execution/my-execution-name/my-execution-id
```

**Obtenção do histórico de execução**  
Visualize o histórico de pontos de verificação de uma execução:

```
aws lambda get-durable-execution-history \
  --durable-execution-arn arn:aws:lambda:us-east-1:123456789012:function:myDurableFunction:my-function-version/durable-execution/my-execution-name/my-execution-id
```

**Interrupção de uma execução**  
Interrompa uma execução durável em andamento:

```
aws lambda stop-durable-execution \
  --durable-execution-arn arn:aws:lambda:us-east-1:123456789012:function:myDurableFunction:my-function-version/durable-execution/my-execution-name/my-execution-id
```

## Atualizar um código de função
<a name="durable-cli-update-function"></a>

Atualize o código da sua função durável e publique uma nova versão:

**Para atualizar e publicar uma nova versão**

1. Atualize o código da função:

   ```
   aws lambda update-function-code \
     --function-name myDurableFunction \
     --zip-file fileb://function.zip
   ```

1. Aguarde até que a atualização seja concluída:

   ```
   aws lambda wait function-updated \
     --function-name myDurableFunction
   ```

1. Publique uma nova versão:

   ```
   aws lambda publish-version \
     --function-name myDurableFunction \
     --description "Updated order processing logic"
   ```

1. Atualize o alias para apontar para a nova versão.

   ```
   aws lambda update-alias \
     --function-name myDurableFunction \
     --name prod \
     --function-version 2
   ```

**Importante**  
As execuções em andamento continuam usando a versão com a qual foram iniciadas. Novas invocações usarão a versão atualizada do alias.

## Visualizar logs de função
<a name="durable-cli-view-logs"></a>

Visualize os logs da sua função durável no CloudWatch Logs:

```
aws logs tail /aws/lambda/myDurableFunction --follow
```

Filtre logs para uma execução específica:

```
aws logs filter-log-events \
  --log-group-name /aws/lambda/myDurableFunction \
  --filter-pattern "exec-abc123"
```

## Limpar os recursos
<a name="durable-cli-cleanup"></a>

Exclua sua função durável e os recursos associados:

```
# Delete the function
aws lambda delete-function --function-name myDurableFunction

# Delete the IAM role policies
aws iam detach-role-policy \
  --role-name durable-function-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

aws iam detach-role-policy \
  --role-name durable-function-role \
  --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy

# Delete the role
aws iam delete-role --role-name durable-function-role
```

## Próximas etapas
<a name="durable-cli-next-steps"></a>

Depois de implantar sua função durável com a AWS CLI:
+ Monitore as execuções usando os comandos `list-durable-executions` e `get-durable-execution`
+ Visualize as operações de ponto de verificação em eventos de dados do AWS CloudTrail
+ Configure os alarmes do CloudWatch para falhas de execução ou execuções de longa duração
+ Automatize as implantações usando scripts de shell ou pipelines de CI/CD

Para obter mais informações sobre os comandos da AWS CLI para o Lambda, consulte a [Referência de comandos da AWS CLI](https://docs.aws.amazon.com/cli/latest/reference/lambda/index.html).

# Implemente funções duráveis do Lambda com infraestrutura como código
<a name="durable-getting-started-iac"></a>

É possível implantar funções duráveis do Lambda usando ferramentas de infraestrutura como código (IaC) como AWS CloudFormation, AWS CDK, AWS Serverless Application Model ou Terraform. Essas ferramentas permitem que você defina sua função, perfil de execução e permissões no código, tornando as implantações repetíveis e controladas por versão.

Todas as três ferramentas exigem que você:
+ Habilite a execução durável da função
+ Conceda permissões de ponto de verifica';cão para o perfil de execução
+ Publique uma versão ou crie um alias (funções duráveis exigem ARNs qualificados)

## Funcionalidades duradouras a partir de um ZIP
<a name="durable-iac-zip"></a>

### AWS CloudFormation
<a name="durable-iac-cloudformation"></a>

Use CloudFormation para definir sua função durável em um modelo. O exemplo a seguir cria uma função durável com as permissões necessárias.

```
AWSTemplateFormatVersion: '2010-09-09'
Description: Lambda durable function example

Resources:
  DurableFunctionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy

  DurableFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: myDurableFunction
      Runtime: nodejs22.x
      Handler: index.handler
      Role: !GetAtt DurableFunctionRole.Arn
      Code:
        ZipFile: |
          // Your durable function code here
          export const handler = async (event, context) => {
            return { statusCode: 200 };
          };
      DurableConfig:
        ExecutionTimeout: 3600
        RetentionPeriodInDays: 7

  DurableFunctionVersion:
    Type: AWS::Lambda::Version
    Properties:
      FunctionName: !Ref DurableFunction
      Description: Initial version

  DurableFunctionAlias:
    Type: AWS::Lambda::Alias
    Properties:
      FunctionName: !Ref DurableFunction
      FunctionVersion: !GetAtt DurableFunctionVersion.Version
      Name: prod

Outputs:
  FunctionArn:
    Description: Durable function ARN
    Value: !GetAtt DurableFunction.Arn
  AliasArn:
    Description: Function alias ARN (use this for invocations)
    Value: !Ref DurableFunctionAlias
```

**Para implantar o modelo**

```
aws cloudformation deploy \
  --template-file template.yaml \
  --stack-name my-durable-function-stack \
  --capabilities CAPABILITY_IAM
```

### AWS CDK
<a name="durable-iac-cdk"></a>

AWS CDK permite definir a infraestrutura usando linguagens de programação. Os exemplos a seguir mostram como criar uma função durável usando TypeScript e Python.

------
#### [ TypeScript ]

```
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class DurableFunctionStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create the durable function
    const durableFunction = new lambda.Function(this, 'DurableFunction', {
      runtime: lambda.Runtime.NODEJS_22_X,
      handler: 'index.handler',
      code: lambda.Code.fromAsset('lambda'),
      functionName: 'myDurableFunction',
      durableConfig: { executionTimeout: Duration.hours(1), retentionPeriod: Duration.days(30) },
    });

    // Create version and alias
    const version = durableFunction.currentVersion;
    const alias = new lambda.Alias(this, 'ProdAlias', {
      aliasName: 'prod',
      version: version,
    });

    // Output the alias ARN
    new cdk.CfnOutput(this, 'FunctionAliasArn', {
      value: alias.functionArn,
      description: 'Use this ARN to invoke the durable function',
    });
  }
}
```

------
#### [ Python ]

```
from aws_cdk import (
    Stack,
    aws_lambda as lambda_,
    aws_iam as iam,
    CfnOutput,
)
from constructs import Construct

class DurableFunctionStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)

        # Create the durable function
        durable_function = lambda_.Function(
            self, 'DurableFunction',
            runtime=lambda_.Runtime.NODEJS_22_X,
            handler='index.handler',
            code=lambda_.Code.from_asset('lambda'),
            function_name='myDurableFunction',
            durable_execution={execution_timeout: Duration.hours(1), retention_period: Duration.days(30)}
        )

        # Add durable execution managed policy for checkpoint permissions
        durable_function.role.add_managed_policy(
            iam.ManagedPolicy.from_aws_managed_policy_name('service-role/AWSLambdaBasicDurableExecutionRolePolicy')
        )

        # Create version and alias
        version = durable_function.current_version
        alias = lambda_.Alias(
            self, 'ProdAlias',
            alias_name='prod',
            version=version
        )

        # Output the alias ARN
        CfnOutput(
            self, 'FunctionAliasArn',
            value=alias.function_arn,
            description='Use this ARN to invoke the durable function'
        )
```

------

**Para implantar a pilha do CDK**

```
cdk deploy
```

### AWS Serverless Application Model
<a name="durable-iac-sam"></a>

O AWS SAM simplifica os modelos do CloudFormation para aplicações com tecnologia sem servidor. O modelo a seguir cria uma função durável com o AWS SAM.

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda durable function with SAM

Resources:
  DurableFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: myDurableFunction
      Runtime: nodejs22.x
      Handler: index.handler
      CodeUri: ./src
      DurableConfig:
        ExecutionTimeout: 3600
        RetentionPeriodInDays: 7
      Policies:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy
      AutoPublishAlias: prod

Outputs:
  FunctionArn:
    Description: Durable function ARN
    Value: !GetAtt DurableFunction.Arn
  AliasArn:
    Description: Function alias ARN (use this for invocations)
    Value: !Ref DurableFunction.Alias
```

**Para implantar o modelo do SAM**

```
sam build
sam deploy --guided
```

### Terraform
<a name="durable-iac-terraform"></a>

O Terraform é uma ferramenta popular de IaC de código aberto que oferece suporte a recursos de AWS. O exemplo a seguir cria uma função durável com o Terraform usando a versão 6.25.0 ou posterior do provedor AWS.

```
terraform {
  required_version = ">= 1.0"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 6.25.0"
    }
  }
}

provider "aws" {
  region = "us-east-2"
}

# IAM Role for Lambda Function
resource "aws_iam_role" "lambda_role" {
  name = "durable-function-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Action = "sts:AssumeRole"
      Effect = "Allow"
      Principal = {
        Service = "lambda.amazonaws.com"
      }
    }]
  })
}

# Attach durable execution policy for checkpoint operations
resource "aws_iam_role_policy_attachment" "lambda_durable" {
  policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy"
  role       = aws_iam_role.lambda_role.name
}

# Lambda Function with Durable Execution enabled
resource "aws_lambda_function" "durable_function" {
  filename      = "function.zip"
  function_name = "myDurableFunction"
  role          = aws_iam_role.lambda_role.arn
  handler       = "index.handler"
  runtime       = "nodejs22.x"
  timeout       = 30
  memory_size   = 512

  durable_config {
    execution_timeout = 900
    retention_period  = 7
  }
}

# Publish a version
resource "aws_lambda_alias" "prod" {
  name             = "prod"
  function_name    = aws_lambda_function.durable_function.function_name
  function_version = aws_lambda_function.durable_function.version
}

output "function_arn" {
  description = "ARN of the Lambda function"
  value       = aws_lambda_function.durable_function.arn
}

output "alias_arn" {
  description = "ARN of the function alias (use this for invocations)"
  value       = aws_lambda_alias.prod.arn
}
```

**Para implantar com o Terraform**

```
terraform init
terraform plan
terraform apply
```

**nota**  
O suporte do Terraform para funções duráveis do Lambda requer a versão 6.25.0 ou posterior do provedor AWS. Atualize a versão do seu provedor se você estiver usando uma versão mais antiga.

## Funções duráveis a partir de uma imagem de contêiner OCI
<a name="durable-iac-oci"></a>

Ainda é possível criar funções Durable com base em imagens de contêiner. Para obter instruções sobre como criar uma imagem de contêiner, consulte [Runtimes compatíveis com funções duráveis](durable-supported-runtimes.md).

### AWS CDK
<a name="durable-iac-oci-cdk"></a>

AWS CDK permite definir a infraestrutura usando linguagens de programação. Os exemplos a seguir mostram como criar uma função durável usando TypeScript a partir de uma imagem de contêiner.

```
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class DurableFunctionStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Create the durable function
    const durableFunction = new lambda.DockerImageFunction(this, 'DurableFunction', {
      code: lambda.DockerImageCode.fromImageAsset('./lambda', {
        platform: cdk.aws_ecr_assets.Platform.LINUX_AMD64,
      }),
      functionName: 'myDurableFunction',
      memorySize: 512,
      timeout: cdk.Duration.seconds(30),
      durableConfig: { executionTimeout: cdk.Duration.hours(1), retentionPeriod: cdk.Duration.days(30) },
    });

    // Create version and alias
    const version = durableFunction.currentVersion;
    const alias = new lambda.Alias(this, 'ProdAlias', {
      aliasName: 'prod',
      version: version,
    });

    // Output the alias ARN
    new cdk.CfnOutput(this, 'FunctionAliasArn', {
      value: alias.functionArn,
      description: 'Use this ARN to invoke the durable function',
    });
  }
}
```

**Para implantar a pilha do CDK**

```
cdk deploy
```

### AWS Serverless Application Model
<a name="durable-iac-oci-sam"></a>

O AWS SAM simplifica os modelos do CloudFormation para aplicações com tecnologia sem servidor. O modelo a seguir cria uma função durável com o AWS SAM.

```
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Lambda durable function with SAM

Resources:
  DurableFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: myDurableFunction
      PackageType: Image
      ImageUri: ./src
      DurableConfig:
        ExecutionTimeout: 3600
        RetentionPeriodInDays: 7
      Policies:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicDurableExecutionRolePolicy
      AutoPublishAlias: prod
    Metadata:
      DockerTag: latest
      DockerContext: ./src
      Dockerfile: Dockerfile

Outputs:
  FunctionArn:
    Description: Durable function ARN
    Value: !GetAtt DurableFunction.Arn
  AliasArn:
    Description: Function alias ARN (use this for invocations)
    Value: !Ref DurableFunction.Alias
```

**Para implantar o modelo do SAM**

```
sam build
sam deploy --guided
```

## Padrões de configuração comuns
<a name="durable-iac-common-patterns"></a>

Independentemente de qual ferramenta de IaC você usar, siga estes padrões para funções duráveis:

**Habilitação da execução durável**  
Defina a propriedade `DurableConfig` em sua função para permitir uma execução durável. Essa propriedade só estará disponível ao criar a função. Não é possível habilitar execuções duráveis em funções existentes.

**Concessão de permissões de ponto de verificação**  
Anexe a política gerenciada `AWSLambdaBasicDurableExecutionRolePolicy` ao perfil de execução. Essa política inclui as permissões obrigatórias de `lambda:CheckpointDurableExecutions` e `lambda:GetDurableExecutionState`.

**Use ARNs qualificados**  
Crie um uma versão ou alias para a sua função. As funções duráveis exigem ARNs qualificados (com versão ou alias) para invocação. Use `AutoPublishAlias` no AWS SAM ou crie versões explícitas no CloudFormation, AWS CDK e Terraform.

**Dependências de pacotes**  
Inclua o SDK de execução durável em seu pacote de implantação. Para o Node.js, instale `@aws/durable-execution-sdk-js`. Para Python, instale `aws-durable-execution-sdk-python`.

## Próximas etapas
<a name="durable-iac-next-steps"></a>

Depois de implantar sua função durável:
+ Teste sua função usando o ARN qualificado (versão ou alias)
+ Monitore o progresso da execução no console do Lambda, na guia Execuções duráveis
+ Visualize as operações de ponto de verificação em eventos de dados do AWS CloudTrail
+ Analise o CloudWatch Logs para analisar a saída da função e o comportamento de reprodução

Para obter mais informações sobre como implantar funções do Lambda com ferramentas de IaC, consulte:
+ [CloudFormation Referência de AWS::Lambda::Function do](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)
+ [AWS CDK Documentação do módulo Lambda do](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_lambda-readme.html)
+ [AWS SAM Guia do desenvolvedor do](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html)

# Funções duráveis ou Step Functions
<a name="durable-step-functions"></a>

Tanto as funções duráveis do Lambda quanto o AWS Step Functions permitem a orquestração confiável do fluxo de trabalho com gerenciamento automático de estados e recuperação de falhas. Eles atendem a diferentes preferências do desenvolvedor e padrões arquitetônicos. As funções duráveis são otimizadas para o desenvolvimento de aplicativos no Lambda, enquanto o Step Functions é criado para orquestração de fluxo de trabalho entre serviços da AWS.

## Quando usar as funções duráveis
<a name="durable-sfn-when-durable"></a>

Use funções duráveis quando:
+ Sua equipe prefere linguagens de programação padrão e ferramentas de desenvolvimento conhecidas
+ A lógica do seu aplicativo está principalmente nas funções do Lambda
+ Você quer controle refinado sobre o estado de execução no código
+ Você está criando aplicativos centrados em Lambda com acoplamento forte entre fluxo de trabalho e lógica de negócios
+ Você quer iterar rapidamente sem alternar entre código e designers visuais/JSON

## Quando usar o Step Functions
<a name="durable-sfn-when-step"></a>

Use Step Functions quando:
+ Você precisa de uma representação visual do fluxo de trabalho para visibilidade entre equipes
+ Você está orquestrando vários serviços da AWS e quer integrações nativas sem código SDK personalizado
+ Você precisa de uma infraestrutura de manutenção zero (sem patches, atualizações de runtime)
+ As partes interessadas não técnicas precisar entender e validar a lógica do fluxo de trabalho

## Estrutura de decisão
<a name="durable-sfn-decision-framework"></a>

Use as seguintes perguntas para determinar qual o serviço mais adequado ao seu caso de uso:
+ **Qual é o seu foco principal?** Desenvolvimento de aplicativos em Lambda → funções duráveis. Orquestração do fluxo de trabalho na AWS → Step Functions.
+ **Qual é o seu modelo de programação preferencial?** Linguagens de programação padrão → funções duráveis. DSL baseado em gráficos ou designer visual → Step Functions.
+ **Quantos serviços da AWS estão envolvidos?** Principalmente Lambda → funções duráveis. Vários serviços da AWS → Step Functions.
+ **Quais ferramentas de desenvolvimento você usa?** Experiência de desenvolvedor Lambda, IDE com agente LLM, estruturas de teste de unidade específicas da linguagem de programação, AWS SAM, AWS CDK, AWS Toolkit → funções duráveis. Construtor de fluxo de trabalho visual, AWS CDK para modelar fluxos de trabalho → Step Functions.
+ **Quem gerencia a infraestrutura?** Quer flexibilidade no Lambda → funções duráveis. Quer gerenciamento completo e sem manutenção → Step Functions.

## Comparação de recursos
<a name="durable-sfn-comparison"></a>

A tabela a seguir compara os principais recursos entre o Step Functions e as funções duráveis do Lambda:


| Recurso | AWS Step Functions | Funções duráveis do Lambda | 
| --- | --- | --- | 
| Foco principal | Orquestração do fluxo de trabalho na AWS | Desenvolvimento de aplicações no Lambda | 
| Tipo de serviço | Serviço de fluxo de trabalho independente e dedicado | Execução no Lambda | 
| Modelo de programação | Baseado em gráficos, Amazon States Language DSL ou AWS CDK | Linguagens de programação padrão (JavaScript/TypeScript, Python) | 
| Ferramentas de desenvolvimento | Construtor visual na extensão IDE do Console/AWS Toolkit, AWS CDK | Lambda DX em agentes de IDE e LLM, estruturas de teste de unidade, AWS SAM, extensão IDE do AWS Toolkit | 
| Integrações | Mais de 220 serviços da AWS, 16 mil APIs | Extensão do modelo de programação orientada por eventos do Lambda (origens de eventos) | 
| Gerenciamento | Totalmente gerenciado, independente do runtime, sem manutenção (sem patches, atualizações de runtime) | Gerenciado no ambiente do Lambda | 
| Melhor para | Automação de processos de negócios e TI, processamento de dados, fluxos de trabalho de IA | Transações distribuídas, lógica de aplicação com estado, orquestração de funções, processamento de dados, fluxos de trabalho de IA | 

## Arquiteturas híbridas
<a name="durable-sfn-hybrid"></a>

Muitas aplicações se beneficiam do uso dos dois serviços. Um padrão comum é usar funções duráveis para lógica em nível de aplicação no Lambda, enquanto o Step Functions coordena fluxos de trabalho de alto nível em vários serviços da AWS além das funções do Lambda.

## Considerações sobre a migração
<a name="durable-sfn-migration"></a>

**Começando de maneira simples, evoluindo para algo complexo:** comece com funções duráveis para fluxos de trabalho centrados no Lambda. Adicione o Step Functions quando precisar de orquestração de vários serviços ou design visual de fluxo de trabalho.

**Usuários existentes do Step Functions:** mantenha o Step Functions para fluxos de trabalho estabelecidos entre serviços. Considere as funções duráveis para a nova lógica de aplicação do Lambda que precisa de confiabilidade.

## Recursos relacionados
<a name="durable-sfn-related"></a>
+ [Funções duráveis do Lambda](durable-functions.md)
+ [Orquestrar funções do Lambda com o Step Functions](with-step-functions.md)
+ [Conceitos básicos das funções duráveis](durable-getting-started.md)

# Casos de uso e exemplos
<a name="durable-examples"></a>

As funções duráveis do Lambda permitem que você crie aplicações com tolerância a falhas de várias etapas usando operações duráveis, como etapas e esperas. Com o ponto de verificação automático e um modelo de reprodução de ponto de verificação, em que a execução é reiniciada do início após a falha, mas ignora os pontos de verificação concluídos, suas funções podem se recuperar das falhas e retomar a execução sem perder o progresso.

## Processos com tolerância a falhas de curta duração
<a name="durable-examples-short-lived"></a>

Use funções duráveis para criar operações confiáveis que normalmente são concluídas em minutos. Embora esses processos sejam mais curtos do que os fluxos de trabalho de longa duração, eles ainda se beneficiam da verificação automática e da tolerância a falhas em sistemas distribuídos. Funções duráveis ajudam seus processos de várias etapas a serem concluídos com êxito, mesmo quando as chamadas de serviço individuais falham, sem exigir tratamento complexo de erros ou código de gerenciamento de estado.

Os cenários comuns incluem sistemas de reserva de hotéis, plataformas de reserva de restaurantes, solicitações de viagens compartilhadas, compra de ingressos para eventos e atualizações de assinaturas de SaaS. Esses cenários compartilham características comuns: várias chamadas de serviço que devem ser concluídas juntas, a necessidade de nova tentativa automática em caso de falhas transitórias e a exigência de manter um estado consistente em todos os sistemas distribuídos.

### Transações distribuídas entre microsserviços
<a name="durable-examples-distributed-transactions"></a>

Coordene pagamentos, inventário e envios em vários serviços com reversão automática em caso de falhas. Cada operação de serviço é agrupada em uma etapa, garantindo que a transação possa ser recuperada a qualquer momento se um serviço falhar.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { orderId, amount, items } = event;
    
    // Reserve inventory across multiple warehouses
    const inventory = await context.step("reserve-inventory", async () => {
      return await inventoryService.reserve(items);
    });
    
    // Process payment
    const payment = await context.step("process-payment", async () => {
      return await paymentService.charge(amount);
    });
    
    // Create shipment
    const shipment = await context.step("create-shipment", async () => {
      return await shippingService.createShipment(orderId, inventory);
    });
    
    return { orderId, status: 'completed', shipment };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution

@durable_execution
def lambda_handler(event, context: DurableContext):
    order_id = event['orderId']
    amount = event['amount']
    items = event['items']
    
    # Reserve inventory across multiple warehouses
    inventory = context.step(
        lambda _: inventory_service.reserve(items),
        name='reserve-inventory'
    )
    
    # Process payment
    payment = context.step(
        lambda _: payment_service.charge(amount),
        name='process-payment'
    )
    
    # Create shipment
    shipment = context.step(
        lambda _: shipping_service.create_shipment(order_id, inventory),
        name='create-shipment'
    )
    
    return {'orderId': order_id, 'status': 'completed', 'shipment': shipment}
```

------

Se alguma etapa falhar, a função se repetirá automaticamente a partir do último ponto de verificação com êxito. A reserva de inventário persiste mesmo se o processamento do pagamento falhar temporariamente. Quando a função tenta novamente, ela pula a etapa de inventário concluída e prossegue diretamente para o processamento do pagamento. Isso elimina reservas duplicadas e garante um estado consistente em todo o sistema distribuído.

### Processamento de pedidos com várias etapas
<a name="durable-examples-order-processing"></a>

Processe pedidos por meio de validação, autorização de pagamento, alocação de estoque e atendimento com nova tentativa e recuperação automáticas. Cada etapa é verificada, garantindo que o pedido avance mesmo que as etapas individuais falhem e sejam tentadas novamente.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { orderId, customerId, items } = event;
    
    // Validate order details
    const validation = await context.step("validate-order", async () => {
      const customer = await customerService.validate(customerId);
      const itemsValid = await inventoryService.validateItems(items);
      return { customer, itemsValid };
    });
    
    if (!validation.itemsValid) {
      return { orderId, status: 'rejected', reason: 'invalid_items' };
    }
    
    // Authorize payment
    const authorization = await context.step("authorize-payment", async () => {
      return await paymentService.authorize(
        validation.customer.paymentMethod,
        calculateTotal(items)
      );
    });
    
    // Allocate inventory
    const allocation = await context.step("allocate-inventory", async () => {
      return await inventoryService.allocate(items);
    });
    
    // Fulfill order
    const fulfillment = await context.step("fulfill-order", async () => {
      return await fulfillmentService.createShipment({
        orderId,
        items: allocation.allocatedItems,
        address: validation.customer.shippingAddress
      });
    });
    
    return {
      orderId,
      status: 'completed',
      trackingNumber: fulfillment.trackingNumber
    };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution

@durable_execution
def lambda_handler(event, context: DurableContext):
    order_id = event['orderId']
    customer_id = event['customerId']
    items = event['items']
    
    # Validate order details
    def validate_order(_):
        customer = customer_service.validate(customer_id)
        items_valid = inventory_service.validate_items(items)
        return {'customer': customer, 'itemsValid': items_valid}
    
    validation = context.step(validate_order, name='validate-order')
    
    if not validation['itemsValid']:
        return {'orderId': order_id, 'status': 'rejected', 'reason': 'invalid_items'}
    
    # Authorize payment
    authorization = context.step(
        lambda _: payment_service.authorize(
            validation['customer']['paymentMethod'],
            calculate_total(items)
        ),
        name='authorize-payment'
    )
    
    # Allocate inventory
    allocation = context.step(
        lambda _: inventory_service.allocate(items),
        name='allocate-inventory'
    )
    
    # Fulfill order
    fulfillment = context.step(
        lambda _: fulfillment_service.create_shipment({
            'orderId': order_id,
            'items': allocation['allocatedItems'],
            'address': validation['customer']['shippingAddress']
        }),
        name='fulfill-order'
    )
    
    return {
        'orderId': order_id,
        'status': 'completed',
        'trackingNumber': fulfillment['trackingNumber']
    }
```

------

Esse padrão garante que os pedidos nunca fiquem presos em estados intermediários. Se a validação falhar, o pedido será rejeitado antes da autorização de pagamento. Se a autorização de pagamento falhar, o inventário não será alocado. Cada etapa se desenvolve a partir da anterior com nova tentativa e recuperação automáticas.

**Observação**  
A verificação condicional `if (!validation.itemsValid)` está fora de uma etapa e será reexecutada durante a reprodução. Isso é seguro porque é determinístico: sempre produz o mesmo resultado com o mesmo objeto de validação.

## Processos de longa execução
<a name="durable-examples-long-running"></a>

Use funções duráveis para processos que se estendem por horas, dias ou semanas. As operações de espera suspendem a execução sem incorrer em custos computacionais, tornando os processos de longa execução econômicos. Durante os períodos de espera, sua função interrompe a execução e o Lambda recicla o ambiente de execução. Quando chega a hora de retomar, o Lambda invoca sua função novamente e a reproduz a partir do último ponto de verificação.

Esse modelo de execução torna as funções duráveis ideais para processos que precisem ser pausados por longos períodos, seja aguardando decisões humanas, respostas externas do sistema, janelas de processamento programadas ou retardos baseados em tempo. Você paga somente pelo tempo de computação ativo, não pela espera.

Os cenários comuns incluem processos de aprovação de documentos, processamento em lote programado, processos de integração de vários dias, processos de teste de assinatura e sistemas de notificação atrasada. Esses cenários compartilham características comuns: períodos de espera estendidos medidos em horas ou dias, a necessidade de manter o estado de execução em todas essas esperas e requisitos econômicos em que pagar pelo tempo de computação ocioso é proibitivo.

### Aprovações conm humano no loop
<a name="durable-examples-human-in-loop"></a>

Pause a execução para revisões, aprovações ou decisões de documentos, mantendo o estado da execução. A função aguarda retornos de chamada externos sem consumir recursos, sendo retomada automaticamente quando a aprovação é recebida.

Esse padrão é essencial para processos que exijam julgamento humano ou validação externa. A função é suspensa no ponto de retorno de chamada, sem custos computacionais durante a espera. Quando alguém envia sua decisão via API, o Lambda invoca sua função novamente e a reproduz a partir do ponto de verificação, continuando com o resultado da aprovação.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { documentId, reviewers } = event;
    
    // Step 1: Prepare document for review
    const prepared = await context.step("prepare-document", async () => {
      return await documentService.prepare(documentId);
    });
    
    // Step 2: Request approval with callback
    const approval = await context.waitForCallback(
      "approval-callback",
      async (callbackId) => {
        await notificationService.sendApprovalRequest({
          documentId,
          reviewers,
          callbackId,
          expiresIn: 86400
        });
      },
      {
        timeout: { seconds: 86400 }
      }
    );
    
    // Function resumes here when approval is received
    if (approval?.approved) {
      const finalized = await context.step("finalize-document", async () => {
        return await documentService.finalize(documentId, approval.comments);
      });
      
      return {
        status: 'approved',
        documentId,
        finalizedAt: finalized.timestamp
      };
    }
    
    // Handle rejection
    await context.step("archive-rejected", async () => {
      await documentService.archive(documentId, approval?.reason);
    });
    
    return {
      status: 'rejected',
      documentId,
      reason: approval?.reason
    };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution, WaitConfig

@durable_execution
def lambda_handler(event, context: DurableContext):
    document_id = event['documentId']
    reviewers = event['reviewers']
    
    # Step 1: Prepare document for review
    prepared = context.step(
        lambda _: document_service.prepare(document_id),
        name='prepare-document'
    )
    
    # Step 2: Request approval with callback
    def send_approval_request(callback_id):
        notification_service.send_approval_request({
            'documentId': document_id,
            'reviewers': reviewers,
            'callbackId': callback_id,
            'expiresIn': 86400
        })
    
    approval = context.wait_for_callback(
        send_approval_request,
        name='approval-callback',
        config=WaitConfig(timeout=86400)
    )
    
    # Function resumes here when approval is received
    if approval and approval.get('approved'):
        finalized = context.step(
            lambda _: document_service.finalize(document_id, approval.get('comments')),
            name='finalize-document'
        )
        
        return {
            'status': 'approved',
            'documentId': document_id,
            'finalizedAt': finalized['timestamp']
        }
    
    # Handle rejection
    context.step(
        lambda _: document_service.archive(document_id, approval.get('reason') if approval else None),
        name='archive-rejected'
    )
    
    return {
        'status': 'rejected',
        'documentId': document_id,
        'reason': approval.get('reason') if approval else None
    }
```

------

Quando o retorno de chamada é recebido e sua função é retomada, ela é reproduzida desde o início. A etapa de preparação do documento retorna instantaneamente o resultado de verificação. A operação waitForCallback também retorna instantaneamente com o resultado da aprovação armazenado, em vez de esperar novamente. A execução então continua até as etapas de finalização ou arquivamento.

### Pipelines de dados de vários estágios
<a name="durable-examples-data-pipelines"></a>

Processe grandes conjuntos de dados por meio de fases de extração, transformação e carregamento com pontos de verificação entre os estágios. Cada estágio pode levar horas para ser concluído, e os pontos de verificação permitem que o pipeline possa ser retomado a partir de qualquer estágio se for interrompido.

Esse padrão é ideal para fluxos de trabalho de ETL, migrações de dados ou trabalhos de processamento em lote em que você precise processar dados em estágios com pontos de recuperação entre eles. Se um estágio falhar, o pipeline é retomado a partir do último estágio concluído, em vez de ser reiniciado do início. Também é possível usar as operações de espera para pausar entre os estágios, respeitando os limites de taxa, esperando que os sistemas posteriores estejam prontos ou programando o processamento fora do horário de pico.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { datasetId, batchSize } = event;
    
    // Stage 1: Extract data from source
    const extracted = await context.step("extract-data", async () => {
      const records = await sourceDatabase.extractRecords(datasetId);
      return { recordCount: records.length, records };
    });
    
    // Wait 5 minutes to respect source system rate limits
    await context.wait({ seconds: 300 });
    
    // Stage 2: Transform data in batches
    const transformed = await context.step("transform-data", async () => {
      const batches = chunkArray(extracted.records, batchSize);
      const results = [];
      
      for (const batch of batches) {
        const transformed = await transformService.processBatch(batch);
        results.push(transformed);
      }
      
      return { batchCount: batches.length, results };
    });
    
    // Wait until off-peak hours (e.g., 2 AM)
    const now = new Date();
    const targetHour = 2;
    const msUntilTarget = calculateMsUntilHour(now, targetHour);
    await context.wait({ seconds: Math.floor(msUntilTarget / 1000) });
    
    // Stage 3: Load data to destination
    const loaded = await context.step("load-data", async () => {
      let loadedCount = 0;
      
      for (const result of transformed.results) {
        await destinationDatabase.loadBatch(result);
        loadedCount += result.length;
      }
      
      return { loadedCount };
    });
    
    // Stage 4: Verify and finalize
    const verified = await context.step("verify-pipeline", async () => {
      const verification = await destinationDatabase.verifyRecords(datasetId);
      await pipelineService.markComplete(datasetId, verification);
      return verification;
    });
    
    return {
      datasetId,
      recordsProcessed: extracted.recordCount,
      batchesProcessed: transformed.batchCount,
      recordsLoaded: loaded.loadedCount,
      verified: verified.success
    };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution
from datetime import datetime

@durable_execution
def lambda_handler(event, context: DurableContext):
    dataset_id = event['datasetId']
    batch_size = event['batchSize']
    
    # Stage 1: Extract data from source
    def extract_data(_):
        records = source_database.extract_records(dataset_id)
        return {'recordCount': len(records), 'records': records}
    
    extracted = context.step(extract_data, name='extract-data')
    
    # Wait 5 minutes to respect source system rate limits
    context.wait(300)
    
    # Stage 2: Transform data in batches
    def transform_data(_):
        batches = chunk_array(extracted['records'], batch_size)
        results = []
        
        for batch in batches:
            transformed = transform_service.process_batch(batch)
            results.append(transformed)
        
        return {'batchCount': len(batches), 'results': results}
    
    transformed = context.step(transform_data, name='transform-data')
    
    # Wait until off-peak hours (e.g., 2 AM)
    now = datetime.now()
    target_hour = 2
    ms_until_target = calculate_ms_until_hour(now, target_hour)
    context.wait(ms_until_target // 1000)
    
    # Stage 3: Load data to destination
    def load_data(_):
        loaded_count = 0
        
        for result in transformed['results']:
            destination_database.load_batch(result)
            loaded_count += len(result)
        
        return {'loadedCount': loaded_count}
    
    loaded = context.step(load_data, name='load-data')
    
    # Stage 4: Verify and finalize
    def verify_pipeline(_):
        verification = destination_database.verify_records(dataset_id)
        pipeline_service.mark_complete(dataset_id, verification)
        return verification
    
    verified = context.step(verify_pipeline, name='verify-pipeline')
    
    return {
        'datasetId': dataset_id,
        'recordsProcessed': extracted['recordCount'],
        'batchesProcessed': transformed['batchCount'],
        'recordsLoaded': loaded['loadedCount'],
        'verified': verified['success']
    }
```

------

Cada estágio é dividido em uma etapa, criando um ponto de verificação que permite que o pipeline seja retomado a partir de qualquer estágio se for interrompido. A espera de 5 minutos entre a extração e a transformação respeita os limites de taxa do sistema de origem sem consumir recursos computacionais, enquanto a espera até às 2 da manhã programa a dispendiosa operação de carregamento fora do horário de pico.

**Observação**  
A chamada `new Date()` e a função `calculateMsUntilHour()` são etapas externas e serão reexecutadas durante a reprodução. Para operações baseadas em tempo que devam ser consistentes em todas as repetições, calcule o timestamp dentro de uma etapa ou use-o somente para períodos de espera (que são controlados).

## Padrões avançados
<a name="durable-examples-advanced"></a>

Use funções duráveis para criar aplicações complexas de várias etapas que combinem várias operações duráveis, execução paralela, processamento de matrizes, lógica condicional e sondagem. Esses padrões permitem criar aplicações sofisticadas que coordenem muitas tarefas enquanto mantêm a tolerância a falhas e a recuperação automática.

Os padrões avançados vão além de simples etapas sequenciais. É possível executar operações simultaneamente com `parallel()`, processar matrizes com `map()`, aguardar condições externas com `waitForCondition()` e combinar essas primitivas para criar aplicações confiáveis. Cada operação durável cria seus próprios pontos de verificação, para que sua aplicação possa se recuperar de qualquer ponto se for interrompida.

### Processos de integração de usuários
<a name="durable-examples-user-onboarding"></a>

Guie os usuários durante o registro, a verificação de e-mail, a configuração do perfil e a configuração inicial com o tratamento de novas tentativas. Este exemplo combina etapas sequenciais, retornos de chamada e lógica condicional para criar um processo de integração completo.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { userId, email } = event;
    
    // Step 1: Create user account
    const user = await context.step("create-account", async () => {
      return await userService.createAccount(userId, email);
    });
    
    // Step 2: Send verification email
    await context.step("send-verification", async () => {
      return await emailService.sendVerification(email);
    });
    
    // Step 3: Wait for email verification (up to 48 hours)
    const verified = await context.waitForCallback(
      "email-verification",
      async (callbackId) => {
        await notificationService.sendVerificationLink({
          email,
          callbackId,
          expiresIn: 172800
        });
      },
      {
        timeout: { seconds: 172800 }
      }
    );
    
    if (!verified) {
      await context.step("send-reminder", async () => {
        await emailService.sendReminder(email);
      });
      
      return {
        status: "verification_timeout",
        userId,
        message: "Email verification not completed within 48 hours"
      };
    }
    
    // Step 4: Initialize user profile in parallel
    const setupResults = await context.parallel("profile-setup", [
      async (ctx: DurableContext) => {
        return await ctx.step("create-preferences", async () => {
          return await preferencesService.createDefaults(userId);
        });
      },
      
      async (ctx: DurableContext) => {
        return await ctx.step("setup-notifications", async () => {
          return await notificationService.setupDefaults(userId);
        });
      },
      
      async (ctx: DurableContext) => {
        return await ctx.step("create-welcome-content", async () => {
          return await contentService.createWelcome(userId);
        });
      }
    ]);
    
    // Step 5: Send welcome email
    await context.step("send-welcome", async () => {
      const [preferences, notifications, content] = setupResults.getResults();
      return await emailService.sendWelcome({
        email,
        preferences,
        notifications,
        content
      });
    });
    
    return {
      status: "onboarding_complete",
      userId,
      completedAt: new Date().toISOString()
    };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution, WaitConfig
from datetime import datetime

@durable_execution
def lambda_handler(event, context: DurableContext):
    user_id = event['userId']
    email = event['email']
    
    # Step 1: Create user account
    user = context.step(
        lambda _: user_service.create_account(user_id, email),
        name='create-account'
    )
    
    # Step 2: Send verification email
    context.step(
        lambda _: email_service.send_verification(email),
        name='send-verification'
    )
    
    # Step 3: Wait for email verification (up to 48 hours)
    def send_verification_link(callback_id):
        notification_service.send_verification_link({
            'email': email,
            'callbackId': callback_id,
            'expiresIn': 172800
        })
    
    verified = context.wait_for_callback(
        send_verification_link,
        name='email-verification',
        config=WaitConfig(timeout=172800)
    )
    
    if not verified:
        context.step(
            lambda _: email_service.send_reminder(email),
            name='send-reminder'
        )
        
        return {
            'status': 'verification_timeout',
            'userId': user_id,
            'message': 'Email verification not completed within 48 hours'
        }
    
    # Step 4: Initialize user profile in parallel
    def create_preferences(ctx: DurableContext):
        return ctx.step(
            lambda _: preferences_service.create_defaults(user_id),
            name='create-preferences'
        )
    
    def setup_notifications(ctx: DurableContext):
        return ctx.step(
            lambda _: notification_service.setup_defaults(user_id),
            name='setup-notifications'
        )
    
    def create_welcome_content(ctx: DurableContext):
        return ctx.step(
            lambda _: content_service.create_welcome(user_id),
            name='create-welcome-content'
        )
    
    setup_results = context.parallel(
        [create_preferences, setup_notifications, create_welcome_content],
        name='profile-setup'
    )
    
    # Step 5: Send welcome email
    def send_welcome(_):
        results = setup_results.get_results()
        preferences, notifications, content = results[0], results[1], results[2]
        return email_service.send_welcome({
            'email': email,
            'preferences': preferences,
            'notifications': notifications,
            'content': content
        })
    
    context.step(send_welcome, name='send-welcome')
    
    return {
        'status': 'onboarding_complete',
        'userId': user_id,
        'completedAt': datetime.now().isoformat()
    }
```

------

O processo combina etapas sequenciais com pontos de verificação para a criação da conta e envio de e-mail e, em seguida, faz uma pausa de até 48 horas aguardando a verificação do e-mail sem consumir recursos. A lógica condicional manipula caminhos diferentes com base na conclusão ou no tempo limite da verificação. As tarefas de configuração do perfil são executadas simultaneamente usando operações paralelas para reduzir o tempo total de execução, e cada etapa é repetida automaticamente em caso de falhas transitórias para ajudar a integração a ser concluída de maneira confiável.

### Invocações encadeadas ao longo das funções
<a name="durable-examples-chained-invocations"></a>

Invoque outras funções do Lambda de dentro de uma função durável usando `context.invoke()`. A função de chamada é suspensa enquanto aguarda a função invocada ser concluída, criando um ponto de verificação que preserva o resultado. Se a função de chamada for interrompida após a conclusão da função invocada, ela será retomada com o resultado armazenado sem invocar novamente a função.

Use esse padrão quando você tiver funções especializadas que lidem com domínios específicos (validação de clientes, processamento de pagamentos, gerenciamento de inventário) e precisar coordená-las em um fluxo de trabalho. Cada função mantém sua própria lógica e pode ser invocada por várias funções do orquestrador, evitando a duplicação de código.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

// Main orchestrator function
export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { orderId, customerId } = event;
    
    // Step 1: Validate customer by invoking customer service function
    const customer = await context.invoke(
      "validate-customer",
      "arn:aws:lambda:us-east-1:123456789012:function:customer-service:1",
      { customerId }
    );
    
    if (!customer.isValid) {
      return { orderId, status: "rejected", reason: "invalid_customer" };
    }
    
    // Step 2: Check inventory by invoking inventory service function
    const inventory = await context.invoke(
      "check-inventory",
      "arn:aws:lambda:us-east-1:123456789012:function:inventory-service:1",
      { orderId, items: event.items }
    );
    
    if (!inventory.available) {
      return { orderId, status: "rejected", reason: "insufficient_inventory" };
    }
    
    // Step 3: Process payment by invoking payment service function
    const payment = await context.invoke(
      "process-payment",
      "arn:aws:lambda:us-east-1:123456789012:function:payment-service:1",
      {
        customerId,
        amount: inventory.totalAmount,
        paymentMethod: customer.paymentMethod
      }
    );
    
    // Step 4: Create shipment by invoking fulfillment service function
    const shipment = await context.invoke(
      "create-shipment",
      "arn:aws:lambda:us-east-1:123456789012:function:fulfillment-service:1",
      {
        orderId,
        items: inventory.allocatedItems,
        address: customer.shippingAddress
      }
    );
    
    return {
      orderId,
      status: "completed",
      trackingNumber: shipment.trackingNumber,
      estimatedDelivery: shipment.estimatedDelivery
    };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution

# Main orchestrator function
@durable_execution
def lambda_handler(event, context: DurableContext):
    order_id = event['orderId']
    customer_id = event['customerId']
    
    # Step 1: Validate customer by invoking customer service function
    customer = context.invoke(
        'arn:aws:lambda:us-east-1:123456789012:function:customer-service:1',
        {'customerId': customer_id},
        name='validate-customer'
    )
    
    if not customer['isValid']:
        return {'orderId': order_id, 'status': 'rejected', 'reason': 'invalid_customer'}
    
    # Step 2: Check inventory by invoking inventory service function
    inventory = context.invoke(
        'arn:aws:lambda:us-east-1:123456789012:function:inventory-service:1',
        {'orderId': order_id, 'items': event['items']},
        name='check-inventory'
    )
    
    if not inventory['available']:
        return {'orderId': order_id, 'status': 'rejected', 'reason': 'insufficient_inventory'}
    
    # Step 3: Process payment by invoking payment service function
    payment = context.invoke(
        'arn:aws:lambda:us-east-1:123456789012:function:payment-service:1',
        {
            'customerId': customer_id,
            'amount': inventory['totalAmount'],
            'paymentMethod': customer['paymentMethod']
        },
        name='process-payment'
    )
    
    # Step 4: Create shipment by invoking fulfillment service function
    shipment = context.invoke(
        'arn:aws:lambda:us-east-1:123456789012:function:fulfillment-service:1',
        {
            'orderId': order_id,
            'items': inventory['allocatedItems'],
            'address': customer['shippingAddress']
        },
        name='create-shipment'
    )
    
    return {
        'orderId': order_id,
        'status': 'completed',
        'trackingNumber': shipment['trackingNumber'],
        'estimatedDelivery': shipment['estimatedDelivery']
    }
```

------

Cada invocação cria um ponto de verificação na função do orquestrador. Se o orquestrador for interrompido após a conclusão da validação do cliente, ele será retomado a partir desse ponto de verificação com os dados armazenados do cliente, ignorando a invocação da validação. Isso evita chamadas duplicadas para serviços posteriores e garante uma execução consistente em todas as interrupções.

As funções invocadas podem ser funções do Lambda duráveis ou padrão. Se você invocar uma função durável, ela poderá ter seu próprio fluxo de trabalho em várias etapas com esperas e pontos de verificação. O orquestrador simplesmente espera que a execução durável completa termine, recebendo o resultado final.

**nota**  
Não há suporte a invocações entre contas. Todas as funções invocadas devem estar na mesma conta da AWS da função de chamada.

### Processamento em lote com pontos de verificação
<a name="durable-examples-batch-processing"></a>

Processe milhões de registros com recuperação automática do último ponto de verificação com êxito após falhas. Este exemplo demonstra como funções duráveis combinam `map()` operações com fragmentação e limitação de taxa para lidar com o processamento de dados em grande escala.

------
#### [ TypeScript ]

```
import { DurableContext, withDurableExecution } from "@aws/durable-execution-sdk-js";

interface Batch {
  batchIndex: number;
  recordIds: string[];
}

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    const { datasetId, batchSize = 1000 } = event;
    
    // Step 1: Get all record IDs to process
    const recordIds = await context.step("fetch-record-ids", async () => {
      return await dataService.getRecordIds(datasetId);
    });
    
    // Step 2: Split into batches
    const batches: Batch[] = [];
    for (let i = 0; i < recordIds.length; i += batchSize) {
      batches.push({
        batchIndex: Math.floor(i / batchSize),
        recordIds: recordIds.slice(i, i + batchSize)
      });
    }
    
    // Step 3: Process batches with controlled concurrency
    const batchResults = await context.map(
      "process-batches",
      batches,
      async (ctx: DurableContext, batch: Batch, index: number) => {
        const processed = await ctx.step(`batch-${batch.batchIndex}`, async () => {
          const results = [];
          for (const recordId of batch.recordIds) {
            const result = await recordService.process(recordId);
            results.push(result);
          }
          return results;
        });
        
        const validated = await ctx.step(`validate-${batch.batchIndex}`, async () => {
          return await validationService.validateBatch(processed);
        });
        
        return {
          batchIndex: batch.batchIndex,
          recordCount: batch.recordIds.length,
          successCount: validated.successCount,
          failureCount: validated.failureCount
        };
      },
      {
        maxConcurrency: 5
      }
    );
    
    // Step 4: Aggregate results
    const summary = await context.step("aggregate-results", async () => {
      const results = batchResults.getResults();
      const totalSuccess = results.reduce((sum, r) => sum + r.successCount, 0);
      const totalFailure = results.reduce((sum, r) => sum + r.failureCount, 0);
      
      return {
        datasetId,
        totalRecords: recordIds.length,
        batchesProcessed: batches.length,
        successCount: totalSuccess,
        failureCount: totalFailure,
        completedAt: new Date().toISOString()
      };
    });
    
    return summary;
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import DurableContext, durable_execution, MapConfig
from datetime import datetime
from typing import List, Dict

@durable_execution
def lambda_handler(event, context: DurableContext):
    dataset_id = event['datasetId']
    batch_size = event.get('batchSize', 1000)
    
    # Step 1: Get all record IDs to process
    record_ids = context.step(
        lambda _: data_service.get_record_ids(dataset_id),
        name='fetch-record-ids'
    )
    
    # Step 2: Split into batches
    batches = []
    for i in range(0, len(record_ids), batch_size):
        batches.append({
            'batchIndex': i // batch_size,
            'recordIds': record_ids[i:i + batch_size]
        })
    
    # Step 3: Process batches with controlled concurrency
    def process_batch(ctx: DurableContext, batch: Dict, index: int):
        batch_index = batch['batchIndex']
        
        def process_records(_):
            results = []
            for record_id in batch['recordIds']:
                result = record_service.process(record_id)
                results.append(result)
            return results
        
        processed = ctx.step(process_records, name=f'batch-{batch_index}')
        
        validated = ctx.step(
            lambda _: validation_service.validate_batch(processed),
            name=f'validate-{batch_index}'
        )
        
        return {
            'batchIndex': batch_index,
            'recordCount': len(batch['recordIds']),
            'successCount': validated['successCount'],
            'failureCount': validated['failureCount']
        }
    
    batch_results = context.map(
        process_batch,
        batches,
        name='process-batches',
        config=MapConfig(max_concurrency=5)
    )
    
    # Step 4: Aggregate results
    def aggregate_results(_):
        results = batch_results.get_results()
        total_success = sum(r['successCount'] for r in results)
        total_failure = sum(r['failureCount'] for r in results)
        
        return {
            'datasetId': dataset_id,
            'totalRecords': len(record_ids),
            'batchesProcessed': len(batches),
            'successCount': total_success,
            'failureCount': total_failure,
            'completedAt': datetime.now().isoformat()
        }
    
    summary = context.step(aggregate_results, name='aggregate-results')
    
    return summary
```

------

Os registros são divididos em lotes gerenciáveis para evitar sobrecarregar a memória ou os serviços posteriores e, em seguida, vários lotes são processados simultaneamente com `maxConcurrency` controlando o paralelismo. Cada lote tem seu próprio ponto de verificação, portanto, as falhas apenas repetem o lote com falha, em vez de reprocessar todos os registros. Esse padrão é ideal para trabalhos de ETL, migrações de dados ou operações em massa em que o processamento pode levar horas.

## Próximas etapas
<a name="durable-examples-next-steps"></a>
+ Explore [conceitos básicos](durable-basic-concepts.md) para compreender DurableContext, etapas e esperas
+ Analise as [práticas recomendadas](durable-best-practices.md) para escrever código determinístico e otimizar a perfoirmance
+ Saiba mais sobre [testes de funções duráveis](durable-testing.md) localmente e na nuvem
+ Compare funções duráveis com o Step Functions para entender quando cada abordagem é mais eficaz. Consulte [Funções duráveis ou Step Functions](durable-step-functions.md).

# Segurança e permissões para as funções duráveis do Lambda
<a name="durable-security"></a>

As funções duráveis do Lambda exigem permissões específicas do IAM para gerenciar as operações de ponto de verificação. Siga o princípio do privilégio mínimo concedendo somente as permissões de que sua função precisa.

## Permissões da função de execução
<a name="durable-execution-role"></a>

O perfil de execução da sua função durável precisa de permissões para criar pontos de verificação e recuperar o estado de execução. A política a seguir mostra as permissões mínimas necessárias:

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:CheckpointDurableExecution",
                "lambda:GetDurableExecutionState"
            ],
            "Resource": "arn:aws:lambda:region:account-id:function:function-name:*"
        }
    ]
}
```

Quando você cria uma função durável usando o console, o Lambda adiciona automaticamente essas permissões ao perfil de execução. Se você criar a função usando a AWS CLI ou o AWS CloudFormation, adicione essas permissões ao seu perfil de execução.

**Princípio do privilégio mínimo**  
Defina o escopo do elemento `Resource` para ARNs de funções específicas em vez de usar curingas. Isso limita o perfil de execução a operações de ponto de verificação somente para as funções que precisem delas.

**Exemplo: permissões com escopo definido para várias funções**

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:CheckpointDurableExecution",
                "lambda:GetDurableExecutionState"
            ],
            "Resource": [
                "arn:aws:lambda:us-east-1:123456789012:function:orderProcessor:*",
                "arn:aws:lambda:us-east-1:123456789012:function:paymentHandler:*"
            ]
        }
    ]
}
```

Como alternativa, é possível usar a política gerenciada pela AWS `AWSLambdaBasicDurableExecutionRolePolicy`, que inclui as permissões de execução duráveis necessárias junto às permissões básicas de execução do Lambda para o Amazon CloudWatch Logs.

## Criptografia de estado
<a name="durable-state-encryption"></a>

As funções duráveis do Lambda habilitam automaticamente a criptografia em repouso usando chaves de propriedade da AWS sem custos. Cada execução de função mantém um estado isolado que outras execuções não podem acessar. Não há suporte para chaves gerenciadas pelo cliente (CMK).

Os dados do ponto de verificação incluem:
+ Resultados da etapa e valores de retorno
+ Andamento e cronograma da execução
+ Informações de estado de espera

Os dados são criptografados em trânsito usando TLS quando o Lambda lê ou grava dados de pontos de verificação.

### Criptografia personalizada com serializadores e desserializadores personalizados
<a name="durable-custom-encryption"></a>

Para requisitos críticos de segurança, é possível implementar seu próprio mecanismo de criptografia e descriptografia por meio de serializadores e desserializadores personalizados (SerDer) usando um SDK durável. Essa abordagem oferece controle total sobre as chaves de criptografia e os algoritmos usados para proteger os dados dos pontos de verificação.

**Importante**  
Ao usar criptografia personalizada, você perde a visibilidade dos resultados da operação no console do Lambda e nas respostas de APIs. Os dados dos pontos de verificação aparecem criptografados no histórico de execução e não podem ser inspecionados sem a descriptografia.

O perfil de execução da sua função precisa das permissões `kms:Encrypt` e `kms:Decrypt` para a chave AWS KMS usada na implementação SerDer personalizada.

## Registro em log do CloudTrail
<a name="durable-cloudtrail-logging"></a>

O Lambda registra em log as operações de pontos de verificação como eventos de dados em AWS CloudTrail. É possível usar o CloudTrail para auditar a criação de pontos de verificação, rastrear alterações no estado de execução e monitorar o acesso a dados de execução duráveis.

As operações de pontos de verificação aparecem nos logs do CloudTrail com os nomes de eventos a seguir:
+ `CheckpointDurableExecution`: registrado em log quando uma etapa é concluída e um ponto de verificação é criado
+ `GetDurableExecutionState`: registrado em log quando o Lambda recupera o estado de execução durante a reprodução

Para habilitar o registro em log de eventos de dados para funções duráveis, configure uma trilha do CloudTrail para registrar em log eventos de dados do Lambda. Para obter mais informações, consulte [Registro em log de eventos de dados](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html) no Guia do usuário do CloudTrail.

**Exemplo: entrada de log do CloudTrail para operação de ponto de verificação**

```
{
    "eventVersion": "1.08",
    "eventTime": "2024-11-16T10:30:45Z",
    "eventName": "CheckpointDurableExecution",
    "eventSource": "lambda.amazonaws.com",
    "requestParameters": {
        "functionName": "myDurableFunction",
        "executionId": "exec-abc123",
        "stepId": "step-1"
    },
    "responseElements": null,
    "eventType": "AwsApiCall"
}
```

## Considerações sobre o acesso entre contas
<a name="durable-cross-account-access"></a>

Se você invocar funções duráveis em várias contas da AWS, a conta chamadora precisará da permissão `lambda:InvokeFunction`, mas as operações de ponto de verificação sempre usarão o perfil de execução na conta da função. A conta chamadora não pode acessar diretamente os dados do ponto de verificação ou o estado de execução.

Esse isolamento garante que os dados do ponto de verificação permaneçam seguros na conta da função, mesmo quando invocados a partir de contas externas.

## Recursos de segurança herdados do Lambda
<a name="durable-inherited-security"></a>

As funções duráveis herdam todos os atributos de segurança, governança e conformidade do Lambda, incluindo conectividade VPC, criptografia variável de ambiente, filas de mensagens não entregues, simultaneidade reservada, URLs de funções, assinatura de código e certificações de conformidade (SOC, PCI DSS, HIPAA etc.).

Para obter informações detalhadas sobre os recursos de segurança do Lambda, consulte [Segurança no AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/lambda-security.html) no Guia do desenvolvedor do Lambda. As únicas considerações adicionais de segurança para funções duráveis são as permissões de ponto de verificação documentadas neste guia.

# SDK de execução durável
<a name="durable-execution-sdk"></a>

O SDK de execução durável é a base para a criação de funções duráveis. Ele fornece os elementos básicos de que você precisa para verificar o progresso, lidar com novas tentativas e gerenciar o fluxo de execução. O SDK abstrai a complexidade do gerenciamento e da reprodução de pontos de verificação, permitindo que você escreva um código sequencial que automaticamente se torna com tolerância a falhas.

O SDK está disponível para JavaScript, TypeScript, Python e Java (versão prévia). Para obter a documentação completa da API e exemplos, consulte o [JavaScript/TypeScript SDK](https://github.com/aws/aws-durable-execution-sdk-js), o [Python SDK](https://github.com/aws/aws-durable-execution-sdk-python) e o [Java SDK](https://github.com/aws/aws-durable-execution-sdk-java) no GitHub.

## DurableContext
<a name="durable-sdk-context"></a>

O SDK fornece à sua função um objeto `DurableContext` que expõe todas as operações duráveis. Esse contexto substitui o contexto padrão do Lambda e fornece métodos para a criação de pontos de verificação, gerenciamento do fluxo de execução e coordenação com sistemas externos.

Para usar o SDK, encapsule seu manipulador Lambda com o wrapper de execução durável:

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Your function receives DurableContext instead of Lambda context
    // Use context.step(), context.wait(), etc.
    return result;
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext

@durable_execution
def handler(event: dict, context: DurableContext):
    # Your function receives DurableContext
    # Use context.step(), context.wait(), etc.
    return result
```

------
#### [ Java (Preview) ]

```
import software.amazon.lambda.durable.DurableContext;
import software.amazon.lambda.durable.DurableHandler;

public class Handler extends DurableHandler<Object, String> {
    @Override
    public String handleRequest(Object input, DurableContext context) {
        // Your function receives DurableContext
        // Use context.step(), context.wait(), etc.
        return result;
    }
}
```

------

O wrapper intercepta a invocação da sua função, carrega qualquer log de ponto de verificação existente e fornece o `DurableContext` que gerencia a reprodução e a criação dos pontos de verificação.

## O que o SDK faz
<a name="durable-sdk-what-it-does"></a>

O SDK lida com três responsabilidades críticas que habilitam a execução durável:

**Gerenciamento de pontos de verificação:** o SDK cria pontos de verificação automaticamente à medida que sua função executa operações duráveis. Cada ponto de verificação registra o tipo de operação, as entradas e os resultados. Quando sua função conclui uma etapa, o SDK persiste no ponto de verificação antes de prosseguir. Isso garante que sua função possa ser retomada a partir de qualquer operação concluída, caso seja interrompida.

**Coordenação de reprodução:** quando sua função é retomada após uma pausa ou interrupção, o SDK executa a reprodução. Ele executa seu código desde o início, mas ignora as operações concluídas, usando resultados de pontos de verificação armazenados em vez de reexecutá-las. O SDK garante que a reprodução seja determinística, de forma que, dadas as mesmas entradas e o mesmo log do ponto de verificação, sua função produz os mesmos resultados.

**Isolamento de estado:** o SDK mantém o estado de execução separadamente da sua lógica de negócios. Cada execução durável tem seu próprio log de ponto de verificação que outras execuções não podem acessar. O SDK criptografa os dados em repouso do ponto de verificação e garante que o estado permaneça consistente em todas as reproduções.

## Como o ponto de verificação funciona
<a name="durable-sdk-how-checkpointing-works"></a>

Quando você chama uma operação durável, o SDK segue esta sequência:

1. **Verificar o ponto de verificação existente:** o SDK verifica se essa operação já foi concluída em uma invocação anterior. Se existir um ponto de verificação, o SDK retornará o resultado armazenado sem reexecutar a operação.

1. **Executar a operação:** se não existir nenhum ponto de verificação, o SDK executará seu código de operação. Para etapas, isso significa chamar sua função. Para esperas, isso significa agendar a retomada.

1. **Criar ponto de verificação:** após a conclusão da operação, o SDK serializa o resultado e cria um ponto de verificação. O ponto de verificação inclui o tipo de operação, nome, entradas, resultado e timestamp.

1. **Persistir o ponto de verificação:** o SDK chama a API de ponto de verificação do Lambda para persistir o ponto de verificação. Isso garante que o ponto de verificação seja durável antes de prosseguir com a execução.

1. **Retornar resultado:** o SDK retorna o resultado da operação para seu código, que prossegue até a próxima operação.

Essa sequência garante que, após a conclusão da operação, seu resultado seja armazenado com segurança. Se sua função for interrompida em algum momento, o SDK poderá reproduzi-la até o último ponto de verificação concluído.

## Comportamento da reprodução
<a name="durable-sdk-replay-behavior"></a>

Quando sua função é retomada após uma pausa ou interrupção, o SDK executa a reprodução.

1. **Carregar log do ponto de verificação:** o SDK recupera o log do ponto de verificação para essa execução do Lambda.

1. **Executar desde o início:** o SDK invoca sua função de manipulador desde o início, não de onde ela foi pausada.

1. **Ignorar operações duráveis concluídas:** à medida que seu código chama operações duráveis, o SDK compara cada uma delas com base no log do ponto de verificação. Para operações duráveis concluídas, o SDK retorna o resultado armazenado sem executar o código da operação.
**nota**  
Se o resultado do contexto secundário for maior que o tamanho máximo do ponto de verificação (256 KB), o código do contexto será executado novamente durante a reprodução. Isso permite que você construa grandes resultados a partir das operações duráveis executadas dentro do contexto, que serão consultadas no log do ponto de verificação. Portanto, é imperativo executar apenas código determinístico no próprio contexto. Ao usar contextos secundários com grandes resultados, é uma prática recomendada realizar trabalhos de longa duração ou não determinísticos dentro das etapas e realizar apenas tarefas de curta duração que combinem os resultados no próprio contexto.

1. **Retomar no ponto de interrupção:** quando o SDK alcança uma operação sem um ponto de verificação, ele é executado normalmente e cria novos pontos de verificação à medida que as operações duráveis são concluídas.

Esse mecanismo de reprodução exige que seu código seja determinístico. Com as mesmas entradas e o mesmo log do ponto de verificação, sua função deve fazer a mesma sequência de chamadas de operação duráveis. O SDK aplica isso validando se os nomes e tipos de operação correspondem ao log do ponto de verificação durante a reprodução.

## Operações duráveis disponíveis
<a name="durable-sdk-operations"></a>

O `DurableContext` fornece operações para diferentes padrões de coordenação. Cada operação durável cria pontos de verificação automaticamente, garantindo que sua função possa ser retomada a partir de qualquer ponto.

### Etapas
<a name="durable-sdk-op-step"></a>

Executa a lógica de negócios com verificação automática e nova tentativa. Use etapas para operações que chamem serviços externos, realizem cálculos ou executem qualquer lógica que deva ser verificada. O SDK cria um ponto de verificação antes e depois da etapa, armazenando o resultado para reprodução.

------
#### [ TypeScript ]

```
const result = await context.step('process-payment', async () => {
  return await paymentService.charge(amount);
});
```

------
#### [ Python ]

```
result = context.step(
    lambda _: payment_service.charge(amount),
    name='process-payment'
)
```

------
#### [ Java (Preview) ]

```
var result = context.step("process-payment", Payment.class, 
    () -> paymentService.charge(amount)
);
```

------

As etapas oferecem suporte a estratégias de reprodução configuráveis, semântica de execução (no máximo uma vez ou pelo menos uma vez) e serialização personalizada.

### Espera
<a name="durable-sdk-op-wait"></a>

Pausa a execução por um período especificado sem consumir recursos computacionais. O SDK cria um ponto de verificação, encerra a invocação da função e agenda a retomada. Quando a espera é concluída, o Lambda invoca sua função novamente e o SDK faz a reprodução até o ponto de espera antes de prosseguir.

------
#### [ TypeScript ]

```
// Wait 1 hour without charges
await context.wait({ seconds: 3600 });
```

------
#### [ Python ]

```
# Wait 1 hour without charges
context.wait(3600)
```

------
#### [ Java (Preview) ]

```
// Wait 1 hour without charges
context.wait(Duration.ofHours(1));
```

------

### Retornos de chamada
<a name="durable-sdk-op-callback"></a>

Os retornos de chamadas permitem que sua função faça uma pausa e aguarde até que sistemas externos forneçam entrada. Quando você cria um retorno de chamada, o SDK gera um ID de retorno de chamada exclusivo e cria um ponto de verificação. Em seguida, sua função é suspensa (encerra a invocação) sem incorrer em cobranças computacionais. Sistemas externos enviam resultados de retorno de chamada usando as APIs `SendDurableExecutionCallbackSuccess` ou `SendDurableExecutionCallbackFailure` do Lambda. Quando um retorno de chamada é enviado, o Lambda invoca sua função novamente, o SDK faz a reprodução até o ponto de retorno de chamada e sua função prossegue com o resultado do retorno de chamada.

O SDK fornece dois métodos para o trabalho com retornos de chamadas:

**createCallback:** cria um retorno de chamada e retorna uma promessa e um ID de retorno de chamada. Você envia o ID de retorno de chamada para um sistema externo, que envia o resultado usando a API do Lambda.

------
#### [ TypeScript ]

```
const [promise, callbackId] = await context.createCallback('approval', {
  timeout: { hours: 24 }
});

await sendApprovalRequest(callbackId, requestData);
const approval = await promise;
```

------
#### [ Python ]

```
callback = context.create_callback(
    name='approval',
    config=CallbackConfig(timeout_seconds=86400)
)

context.step(
    lambda _: send_approval_request(callback.callback_id),
    name='send_request'
)

approval = callback.result()
```

------
#### [ Java (Preview) ]

```
var config = CallbackConfig.builder(Duration.ofHours(24)).timeout()

var callback = context.createCallback("approval", String.class, config);

context.step("send-request", String.class, () -> {
    notificationService.sendApprovalRequest(callback.callbackId(), requestData);
    return "request-sent";
});

// Blocks until the callback finishes or times out
String approval = callback.get();
```

------

**waitForCallback:** simplifica o tratamento do retorno de chamada combinando a criação e o envio de retornos de chamada em uma única operação. O SDK cria o retorno de chamada, executa sua função de envio com o ID de retorno de chamada e aguarda pelo resultado.

------
#### [ TypeScript ]

```
const result = await context.waitForCallback(
  'external-api',
  async (callbackId, ctx) => {
    await submitToExternalAPI(callbackId, requestData);
  },
  { timeout: { minutes: 30 } }
);
```

------
#### [ Python ]

```
result = context.wait_for_callback(
    lambda callback_id: submit_to_external_api(callback_id, request_data),
    name='external-api',
    config=WaitForCallbackConfig(timeout_seconds=1800)
)
```

------
#### [ Java (Preview) ]

O waitForCallback ainda está em desenvolvimento para Java.

------

Configure os tempos limite para evitar que as funções esperem indefinidamente. Se um retorno de chamada atingir o tempo limite, o SDK lançará um `CallbackError` e sua função poderá tratar o caso de tempo limite. Use tempos limite de pulsação para retornos de chamada de longa duração para detectar quando os sistemas externos param de responder.

Use retornos de chamada para fluxos de trabalho com humanos no loop, integração de sistemas externos, respostas de webhook ou qualquer cenário em que a execução deva ser pausada para entradas externas.

### Execução paralela
<a name="durable-sdk-op-parallel"></a>

Execute várias operações simultaneamente com o controle de simultaneidade opcional. O SDK gerencia a execução paralela, cria pontos de verificação para cada operação e trata as falhas de acordo com sua política de conclusão.

------
#### [ TypeScript ]

```
const results = await context.parallel([
  async (ctx) => ctx.step('task1', async () => processTask1()),
  async (ctx) => ctx.step('task2', async () => processTask2()),
  async (ctx) => ctx.step('task3', async () => processTask3())
]);
```

------
#### [ Python ]

```
results = context.parallel(
    lambda ctx: ctx.step(lambda _: process_task1(), name='task1'),
    lambda ctx: ctx.step(lambda _: process_task2(), name='task2'),
    lambda ctx: ctx.step(lambda _: process_task3(), name='task3')
)
```

------
#### [ Java (Preview) ]

O Parallel ainda está em desenvolvimento para Java.

------

Use `parallel` para executar operações independentes simultaneamente.

### Mapa
<a name="durable-sdk-op-map"></a>

Execute simultaneamente uma operação em cada item em uma matriz com controle de simultaneidade opcional. O SDK gerencia a execução simultânea, cria pontos de verificação para cada operação e trata as falhas de acordo com sua política de conclusão.

------
#### [ TypeScript ]

```
const results = await context.map(itemArray, async (ctx, item, index) =>
  ctx.step('task', async () => processItem(item, index))
);
```

------
#### [ Python ]

```
results = context.map(
    item_array,
    lambda ctx, item, index: ctx.step(
        lambda _: process_item(item, index),
        name='task'
    )
)
```

------
#### [ Java (Preview) ]

O Map ainda está em desenvolvimento para Java.

------

Use `map` para processar matrizes com controle de simultaneidade.

### Contextos secundários
<a name="durable-sdk-op-child-context"></a>

Cria um contexto de execução isolado para operações de agrupamento. Os contextos secundários têm seu próprio log de pontos de verificação e podem conter várias etapas, esperas e outras operações. O SDK trata todo o contexto secundário como uma única unidade para novas tentativas e recuperações.

Use contextos secundários para organizar fluxos de trabalho complexos, implementar subfluxos de trabalho ou isolar operações que devem ser tentadas novamente juntas.

------
#### [ TypeScript ]

```
const result = await context.runInChildContext(
  'batch-processing',
  async (childCtx) => {
    return await processBatch(childCtx, items);
  }
);
```

------
#### [ Python ]

```
result = context.run_in_child_context(
    lambda child_ctx: process_batch(child_ctx, items),
    name='batch-processing'
)
```

------
#### [ Java (Preview) ]

```
var result = context.runInChildContext(
    "batch-processing", 
    String.class, 
    childCtx -> process_batch(childCtx, items)
);
```

------

O mecanismo de reprodução exige que operações duráveis ocorram em uma ordem determinística. Usando vários contextos secundários, é possível ter vários fluxos de trabalho executados simultaneamente, e o determinismo se aplica separadamente em cada contexto. Isso permite que você crie funções de alta performance que utilizem com eficiência vários núcleos de CPU.

Por exemplo, imagine que iniciamos dois contextos secundários, A e B. Na invocação inicial, as etapas dentro dos contextos foram executadas nessa ordem, com as etapas 'A' sendo executadas simultaneamente com as etapas 'B': A1, B1, B2, A2, A3. Na reprodução, o tempo é muito mais rápido, pois os resultados são recuperados do log do ponto de verificação e as etapas são encontradas em uma ordem diferente: B1, A1, A2, B2, A3. Como as etapas 'A' foram encontradas na ordem correta (A1, A2, A3) e as etapas 'B' foram encontradas na ordem correta (B1, B2), a necessidade de determinismo foi satisfeita corretamente.

### Esperas condicionais
<a name="durable-sdk-op-wait-condition"></a>

Sondagens para uma condição com verificação automática entre as tentativas. O SDK executa sua função de verificação, cria um ponto de verificação com o resultado, espera de acordo com sua estratégia e repete até que a condição seja atendida.

------
#### [ TypeScript ]

```
const result = await context.waitForCondition(
  async (state, ctx) => {
    const status = await checkJobStatus(state.jobId);
    return { ...state, status };
  },
  {
    initialState: { jobId: 'job-123', status: 'pending' },
    waitStrategy: (state) => 
      state.status === 'completed' 
        ? { shouldContinue: false }
        : { shouldContinue: true, delay: { seconds: 30 } }
  }
);
```

------
#### [ Python ]

```
result = context.wait_for_condition(
    lambda state, ctx: check_job_status(state['jobId']),
    config=WaitForConditionConfig(
        initial_state={'jobId': 'job-123', 'status': 'pending'},
        wait_strategy=lambda state, attempt: 
            {'should_continue': False} if state['status'] == 'completed'
            else {'should_continue': True, 'delay': 30}
    )
)
```

------
#### [ Java (Preview) ]

O waitForCondition ainda está em desenvolvimento para Java.

------

Use `waitForCondition` para sondar sistemas externos, esperar que os recursos estejam prontos ou implementar novas tentativas com recuo.

### invocação de funções
<a name="durable-sdk-op-invoke"></a>

Invoca uma outra função do Lambda e aguarda seu resultado. O SDK cria um ponto de verificação, invoca a função de destino e retoma sua função quando a invocação é concluída. Isso permite a composição da função e a decomposição do fluxo de trabalho.

------
#### [ TypeScript ]

```
const result = await context.invoke(
  'invoke-processor',
  'arn:aws:lambda:us-east-1:123456789012:function:processor:1',
  { data: inputData }
);
```

------
#### [ Python ]

```
result = context.invoke(
    'arn:aws:lambda:us-east-1:123456789012:function:processor:1',
    {'data': input_data},
    name='invoke-processor'
)
```

------
#### [ Java (Preview) ]

```
var result = context.invoke(
    "invoke-processor", 
    "arn:aws:lambda:us-east-1:123456789012:function:processor:1",
    inputData,
    Result.class, 
    InvokeConfig.builder().build()
);
```

------

## Como as operações duráveis são medidas
<a name="durable-operations-checkpoint-consumption"></a>

Cada operação durável que você executa por `DurableContext` cria pontos de verificação para monitorar o progresso da execução e armazenar dados de estado. Essas operações incorrem em cobranças com base em seu uso, e os pontos de verificação podem conter dados que contribuam para seus custos de gravação e retenção de dados. Os dados armazenados incluem dados de eventos de invocação, cargas úteis retornadas das etapas e dados transmitidos ao concluir retornos de chamada. Entender como as operações duráveis são medidas ajuda você a estimar os custos de execução e a otimizar seus fluxos de trabalho. Para obter detalhes de preços, consulte a [página de dfinição de preços do Lambda](https://aws.amazon.com/lambda/pricing/).

O tamanho da carga útil se refere ao tamanho dos dados serializados em que uma operação durável persiste. Os dados são medidos em bytes e o tamanho pode variar dependendo do serializador usado pela operação. A carga útil de uma operação pode ser o resultado em si de uma conclusão com êxito ou o objeto de erro serializado se a operação falhar.

### Operações básicas
<a name="durable-operations-basic"></a>

As operações básicas são os blocos de construção fundamentais para funções duráveis:


| Operation | Tempo do ponto de verificação | Número de operações | Dados persistidos | 
| --- | --- | --- | --- | 
| Execução | Started | 1 | Tamanho da carga útil da entrada | 
| Execução | Concluído (Com êxito/Falhado/Interrompido) | 0 | Tamanho da carga útil da saída | 
| N.º da etapa | Tentativa nova/Com êxito/Falhado | 1 \$1 N novas tentativas | Tamanho da carga útil retornado de cada tentativa | 
| Aguardar | Started | 1 | N/D | 
| WaitForCondition | Cada tentativa de sondagem | 1 \$1 N sondagens | Tamanho da carga útil retornado de cada tentativa de sondagem | 
| Nova tentativa em nível de invocação | Started | 1 | Carga útil para objeto de erro | 

### Operações de retorno de chamada
<a name="durable-operations-callbacks"></a>

Os retornos de retorno de chamada permitem que sua função faça uma pausa e aguarde até que sistemas externos forneçam entrada. Essas operações criam pontos de verificação quando o retorno de chamada é criado e quando é concluído:


| Operation | Tempo do ponto de verificação | Número de operações | Dados persistidos | 
| --- | --- | --- | --- | 
| CreateCallback | Started | 1 | N/D | 
| Conclusão do retorno de chamada por meio de chamada de API | Completed | 0 | Carga útil de retorno de chamada | 
| WaitForCallback | Started | 3 \$1 N novas tentativas (contexto \$1 retorno de chamada \$1 etapa) | Cargas retornadas pelas tentativas de etapa do remetente, mais duas cópias da carga útil de retorno de chamada | 

### Operações compostas
<a name="durable-operations-compound"></a>

As operações compostas combinam várias operações duráveis para lidar com padrões complexos de coordenação, como execução paralela, processamento de matrizes e contextos aninhados:


| Operation | Tempo do ponto de verificação | Número de operações | Dados persistidos | 
| --- | --- | --- | --- | 
| Paralelo | Started | 1 \$1 N ramificações (1 contexto primário \$1 N contextos secundários) | Até duas cópias do tamanho da carga útil retornada de cada ramificação, mais os status de cada ramificação | 
| mapa | Started | 1 \$1 N ramificações (1 contexto primário \$1 N contextos secundários) | Até duas cópias do tamanho da carga útil retornada de cada iteração, mais os status de cada iteração | 
| Ajudantes de promessas | Completed | 1 | Tamanho da carga útil retornado da promessa | 
| RunInChildContext | Com êxito/Falhado | 1 | Tamanho da carga útil retornado do contexto secundário | 

Para contextos, como de `runInChildContext` ou usados internamente por operações compostas, resultados menores que 256 KB são verificados diretamente. Resultados maiores não são armazenados. Em vez disso, eles são reconstruídos durante a reprodução por meio do reprocessamento das operações do contexto.

# Runtimes com suporte para funções duráveis
<a name="durable-supported-runtimes"></a>

As funções duráveis estão disponíveis para determinados ambientes de runtime gerenciados e imagens de contêineres OCI, proporcionando maior flexibilidade quanto às versões de runtime. É possível criar funções duráveis para Node.js e Python utilizando runtimes gerenciados diretamente no console ou programaticamente por meio da infraestrutura como código. Atualmente, as funções duráveis em Java (Pré-visualização) só podem ser realizadas por meio de imagens de contêiner.

## Runtimes gerenciados pelo Lambda
<a name="durable-managed-runtimes"></a>

Os runtimes gerenciados a seguir oferecem suporte a funções duráveis quando você cria funções no console do Lambda ou usa a AWS CLI com o parâmetro `--durable-config '{"ExecutionTimeout": 3600, "RetentionPeriodInDays": 7}'`. Para obter informações completas sobre os runtimes do Lambda, consulte [Runtimes do Lambda](lambda-runtimes.md).


| Linguagem | Runtime | 
| --- | --- | 
| Node.js | nodejs22.x | 
| Node.js | nodejs24.x | 
| Python | python3.13 | 
| Python | python3.14 | 

**nota**  
Os runtimes do Lambda incluem o SDK de execução durável para testes e desenvolvimento. No entanto, recomendamos incluir o SDK em seu pacote de implantação para produção. Isso garante a consistência da versão e evita possíveis atualizações de runtimes que possam afetar o comportamento da sua função.

### Node.js
<a name="durable-runtime-nodejs"></a>

Instale o SDK no seu projeto de Node.js:

```
npm install @aws/durable-execution-sdk-js
```

O SDK oferece suporte a JavaScript e a TypeScript. Para projetos de TypeScript, o SDK inclui definições de tipo.

### Python
<a name="durable-runtime-python"></a>

Instale o SDK no seu projeto de Python:

```
pip install aws-durable-execution-sdk-python
```

O SDK do Python usa métodos síncronos e não exige `async/await`.

### Java (Pré-visualização)
<a name="durable-runtime-java"></a>

Adicione uma dependência a `pom.xml`:

```
<dependency>
    <groupId>software.amazon.lambda.durable</groupId>
    <artifactId>aws-durable-execution-sdk-java</artifactId>
    <version>VERSION</version>
</dependency>
```

Instale o SDK no seu projeto Java:

```
mvn install
```

Está disponível uma versão de pré-visualização do Java SDK. As operações waitForCondition, waitForCallback, parallel e map ainda estão em desenvolvimento.

## Imagens de contêiner
<a name="durable-container-images"></a>

É possível usar funções duráveis com imagens de contêiner para oferecer suporte a versões adicionais de runtimes ou configurações personalizadas de runtimes. As imagens de contêiner permitem que você use versões de runtimes não disponíveis como runtimes gerenciados ou personalize seu ambiente de runtime.

Para criar uma função durável usando uma imagem de contêiner:

1. Crie um Dockerfile baseado em uma imagem básica do Lambda

1. Instale o SDK de execução durável em seu contêiner

1. Crie e envie a imagem do contêiner para o Amazon Elastic Container Registry

1. Crie a função do Lambda a partir da imagem do contêiner com a execução durável habilitada

### Exemplo de contêiner
<a name="durable-container-python"></a>

Crie um Dockerfile:

------
#### [ Python ]

Crie um Dockerfile para Python 3.11:

```
FROM public.ecr.aws/lambda/python:3.11

# Copy requirements file
COPY requirements.txt ${LAMBDA_TASK_ROOT}/

# Install dependencies including durable SDK
RUN pip install -r requirements.txt

# Copy function code
COPY lambda_function.py ${LAMBDA_TASK_ROOT}/

# Set the handler
CMD [ "lambda_function.handler" ]
```

Crie um arquivo `requirements.txt`:

```
aws-durable-execution-sdk-python
```

------
#### [ Java (Preview) ]

Crie um Dockerfile para Java 25:

```
FROM --platform=linux/amd64 public.ecr.aws/lambda/java:25

# Install Maven
RUN dnf install -y maven

WORKDIR /var/task

# Copy Maven configuration and source code
COPY pom.xml .
COPY src ./src

# Build
RUN mvn clean package -DskipTests

# Move JAR to lib directory
RUN mv target/*.jar lib/

# Set the handler
CMD ["src.path.to.lambdaFunction::handler"]
```

------

Crie e envie a imagem:

```
# Build the image
docker build -t my-durable-function .

# Tag for ECR
docker tag my-durable-function:latest 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-durable-function:latest

# Push to ECR
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-durable-function:latest
```

Crie a função com a execução durável habilitada:

```
aws lambda create-function \
  --function-name myDurableFunction \
  --package-type Image \
  --code ImageUri=123456789012.dkr.ecr.us-east-1.amazonaws.com/my-durable-function:latest \
  --role arn:aws:iam::123456789012:role/lambda-execution-role \
  --durable-config '{"ExecutionTimeout": 3600, "RetentionPeriodInDays": 7}'
```

Para obter mais informações sobre como usar imagens de contêiner com o Lambda, consulte [Criação de imagens de contêiner do Lambda](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html) no Guia do desenvolvedor do Lambda.

## Considerações sobre runtime
<a name="durable-runtime-considerations"></a>

**Gerenciamento de versão do SDK:** inclua o SDK de execução durável em seu pacote de implantação ou imagem de contêiner. Isso garantirá que sua função use uma versão específica do SDK e não seja afetada pelas atualizações de runtimes. Fixe as versões do SDK no seu `package.json` ou `requirements.txt` para controlar quando você fizer o upgrade.

**Atualizações de runtimes:** AWS atualiza os runtimes gerenciados para incluir patches de segurança e correções de erros. Essas atualizações podem incluir novas versões do SDK. Para evitar comportamentos inesperados, inclua o SDK em seu pacote de implantação e teste minuciosamente antes de implantá-lo na produção.

**Tamanho da imagem do contêiner:** as imagens de contêiner têm um tamanho máximo não compactado de 10 GB. O SDK de execução durável adiciona um tamanho mínimo à sua imagem. Otimize seu contêiner usando compilações de vários estágios e removendo dependências desnecessárias.

**Performance de inicialização a frio:** as imagens de contêiner podem ter tempos de inicialização a frio mais longos do que os runtimes gerenciados. O SDK de execução durável tem um impacto mínimo na performance da inicialização a frio. Use a simultaneidade provisionada se a latência da inicialização a frio for essencial para sua aplicação.

# Invocação de funções do Lambda duráveis
<a name="durable-invoking"></a>

As funções do Lambda duráveis oferecem suporte aos mesmos métodos de invocação das funções do Lambda padrão. É possível invocar funções duráveis de forma síncrona, assíncrona ou por meio de mapeamentos da origem do evento. O processo de invocação é idêntico às funções padrão, mas as funções duráveis fornecem recursos adicionais para execuções de longa duração e gerenciamento automático de estados.

## Métodos de invocação
<a name="durable-invoking-methods"></a>

**Invocação síncrona:** invoque uma função durável e aguarde a resposta. As invocações síncronas são limitadas pelo Lambda a 15 minutos (ou menos, dependendo da função configurada e do tempo limite de execução). Use a invocação síncrona quando precisar de resultados imediatos ou ao fazer a integração com APIs e serviços que esperem uma resposta. É possível usar operações de espera para uma computação eficiente sem interromper o chamador. A invocação aguarda a conclusão de toda a execução durável. Para iniciar a execução com idempotência, use o parâmetro do nome da execução conforme descrito em [Idempotência](durable-execution-idempotency.md).

```
aws lambda invoke \
  --function-name my-durable-function:1 \
  --cli-binary-format raw-in-base64-out \
  --payload '{"orderId": "12345"}' \
  response.json
```

**Invocação assíncrona:** coloque um evento na fila para processamento sem esperar por uma resposta. O Lambda coloca o evento em uma fila e retorna imediatamente. Invocações assíncronas oferecem suporte a durações de execução de até um ano. Use a invocação assíncrona para cenários fire-and-forget ou quando o processamento puder ocorrer em segundo plano. Para iniciar a execução com idempotência, use o parâmetro do nome da execução conforme descrito em [Idempotência](durable-execution-idempotency.md).

```
aws lambda invoke \
  --function-name my-durable-function:1 \
  --invocation-type Event \
  --cli-binary-format raw-in-base64-out \
  --payload '{"orderId": "12345"}' \
  response.json
```

**Mapeamentos da origem do evento:** configure o Lambda para invocar automaticamente sua função durável quando os registros estiverem disponíveis em serviços baseados em streaming ou em filas, como o Amazon SQS, o Kinesis ou o DynamoDB. Os mapeamentos da origem do evento sondam a origem do evento e invocam sua função com lotes de registros. Para obter detalhes sobre o uso de mapeamentos da origem do evento com funções duráveis, incluindo limites de duração de execução, consulte [Mapeamentos da origem do evento](durable-invoking-esm.md) com funções duráveis.

Para obter detalhes completos sobre cada método de invocação, consulte [invocação síncrona](invocation-sync.md) e [invocação assíncrona](invocation-async.md).

**nota**  
As funções duráveis oferecem suporte a filas de mensagens não entregues (DLQs) para tratamento de erros, mas não oferecem suporte a destinos do Lambda. Configure uma DLQ para capturar registros de invocações com falhas.

## Requisito de ARNs qualificados
<a name="durable-invoking-qualified-arns"></a>

As funções duráveis exigem identificadores qualificados para invocação. É necessário invocar funções duráveis usando um número de versão, alias ou `$LATEST`. É possível usar um ARN totalmente qualificado ou um nome de função com sufixo de versão/alias. Não é possível usar um identificador não qualificado (sem uma versão ou sufixo de alias).

**Invocações válidas:**

```
# Using full ARN with version number
arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1

# Using full ARN with alias
arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:prod

# Using full ARN with $LATEST
arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:$LATEST

# Using function name with version number
my-durable-function:1

# Using function name with alias
my-durable-function:prod
```

**Invocações inválidas:**

```
# Unqualified ARN (not allowed)
arn:aws:lambda:us-east-1:123456789012:function:my-durable-function

# Unqualified function name (not allowed)
my-durable-function
```

Esse requisito garante que as execuções duráveis permaneçam consistentes durante todo o seu ciclo de vida. Quando uma execução durável é iniciada, ela é fixada na versão específica da função. Se sua função for pausada e retomada horas ou dias depois, o Lambda invocará a mesma versão que iniciou a execução, garantindo a consistência do código em todo o fluxo de trabalho.

**Melhor prática**  
Use aliases ou versões numeradas para funções duráveis de produção, em vez de `$LATEST`. As versões numeradas são imutáveis e permitem uma reprodução determinística. Opcionalmente, os aliases fornecem uma referência estável que pode ser atualizada para apontar para novas versões sem alterar o código de invocação. Quando você atualiza um alias, as novas execuções usam a nova versão, enquanto as execuções em andamento continuam com a versão original. É possível usar `$LATEST` para prototipagem ou para reduzir os tempos de implantação durante o desenvolvimento, entendendo que as execuções podem não ser reproduzidas corretamente (ou até mesmo falhar) se o código subjacente mudar durante o andamento das execuções.

## Noções básicas sobre o ciclo de vida da execução
<a name="durable-invoking-execution-lifecycle"></a>

Quando você invoca uma função durável, o Lambda cria uma execução durável que pode abranger várias invocações de funções:

1. **Invocação inicial:** sua solicitação de invocação cria uma nova execução durável. O Lambda atribui um ID de execução exclusivo e inicia o processamento.

1. **Execução e criação de pontos de verificação:** à medida que sua função executa operações duráveis, o SDK cria pontos de verificação que monitoram o andamento.

1. **Suspensão (se necessário):** se sua função usa esperas duráveis, como `wait` ou `waitForCallback`, ou novas tentativas automáticas de etapas, o Lambda suspende a execução e interrompe a cobrança pelo tempo de computação.

1. **Retomada:** na hora de prosseguir (inclusive após novas tentativas), o Lambda invoca sua função novamente. O SDK reproduz o log do ponto de verificação e continua de onde a execução foi pausada.

1. **Conclusão:** quando sua função retorna um resultado final ou gera um erro não tratado, a execução durável é concluída.

Para invocações síncronas, o chamador espera que toda a execução durável seja concluída, incluindo qualquer operação de espera. Se a execução exceder o tempo limite de invocação (15 minutos ou menos), a invocação expirará. Para invocações assíncronas, o Lambda retorna imediatamente e a execução continua de forma independente. Use as APIs de execução durável para monitorar o status da execução e recuperar os resultados finais.

## Invocação a partir do código da aplicação
<a name="durable-invoking-with-sdk"></a>

Use os SDKs da AWS para invocar funções duráveis a partir do código da sua aplicação. O processo de invocação é idêntico às funções padrão:

------
#### [ TypeScript ]

```
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';

const client = new LambdaClient({});

// Synchronous invocation
const response = await client.send(new InvokeCommand({
  FunctionName: 'arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
  Payload: JSON.stringify({ orderId: '12345' })
}));

const result = JSON.parse(Buffer.from(response.Payload!).toString());

// Asynchronous invocation
await client.send(new InvokeCommand({
  FunctionName: 'arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
  InvocationType: 'Event',
  Payload: JSON.stringify({ orderId: '12345' })
}));
```

------
#### [ Python ]

```
import boto3
import json

client = boto3.client('lambda')

# Synchronous invocation
response = client.invoke(
    FunctionName='arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
    Payload=json.dumps({'orderId': '12345'})
)

result = json.loads(response['Payload'].read())

# Asynchronous invocation
client.invoke(
    FunctionName='arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
    InvocationType='Event',
    Payload=json.dumps({'orderId': '12345'})
)
```

------

## Invocações encadeadas
<a name="durable-invoking-chained"></a>

Funções duráveis podem invocar outras funções duráveis e não duráveis usando a operação `invoke` do `DurableContext`. Isso cria uma invocação em cadeia em que a função de chamada espera (é suspendida) até que a função invocada seja concluída:

------
#### [ TypeScript ]

```
export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Invoke another durable function and wait for result
    const result = await context.invoke(
      'process-order',
      'arn:aws:lambda:us-east-1:123456789012:function:order-processor:1',
      { orderId: event.orderId }
    );
    
    return { statusCode: 200, body: JSON.stringify(result) };
  }
);
```

------
#### [ Python ]

```
@durable_execution
def handler(event, context: DurableContext):
    # Invoke another durable function and wait for result
    result = context.invoke(
        'arn:aws:lambda:us-east-1:123456789012:function:order-processor:1',
        {'orderId': event['orderId']},
        name='process-order'
    )
    
    return {'statusCode': 200, 'body': json.dumps(result)}
```

------

Invocações encadeadas criam um ponto de verificação na função de chamada. Se a função de chamada for interrompida, ela será retomada a partir do ponto de verificação com o resultado da função invocada sem invocar novamente a função.

**nota**  
Não há suporte para invocações encadeadas entre contas. A função invocada deve estar na mesma conta da AWS da função de chamada.

# Mapeamentos da origem do evento com funções duráveis
<a name="durable-invoking-esm"></a>

As funções duráveis funcionam com todos os mapeamentos da origem do evento do Lambda Configure mapeamentos da origem do evento para funções duráveis da mesma forma que você os configura para funções padrão. Os mapeamentos da origem do evento sondam automaticamente fontes de eventos como o Amazon SQS, o Kinesis e o DynamoDB Streams e invocam sua função com lotes de registros.

Os mapeamentos da origem do evento são úteis para funções duráveis que processem fluxos ou filas com fluxos de trabalho complexos de várias etapas. Por exemplo, é possível criar uma função durável que processe mensagens do Amazon SQS com novas tentativas, chamadas de API externas e aprovações humanas.

## Como os mapeamentos da origem do evento invocam as funções duráveis
<a name="durable-esm-invocation-behavior"></a>

Os mapeamentos da origem do evento invocam as funções duráveis de forma síncrona, aguardando a conclusão da execução durável completa antes de processar o próximo lote ou marcar os registros como processados. Se o tempo total de execução durável exceder 15 minutos, a execução expirará e falhará. O mapeamento da origem do evento recebe uma exceção de tempo limite e a trata de acordo com sua configuração de nova tentativa.

## Limite de execução de 15 minutos
<a name="durable-esm-duration-limit"></a>

Quando as funções duráveis são invocadas por mapeamentos da origem do evento, a duração total da execução durável não pode exceder 15 minutos. Esse limite se aplica a toda a execução durável, do início à conclusão, e não apenas às invocações de funções individuais.

Esse limite de 15 minutos é separado do tempo limite da função do Lambda (também de 15 minutos, no máximo). O tempo limite da função controla por quanto tempo cada invocação individual pode ser executada, enquanto o tempo limite de execução durável controla o tempo total decorrido do início à conclusão da execução.

**Cenários de exemplo:**
+ **Válido:** uma função durável processa uma mensagem do Amazon SQS com três etapas, cada uma levando 2 minutos, depois espera 5 minutos antes de concluir a etapa final. Tempo total de execução: 11 minutos. Isso funciona porque o total é inferior a 15 minutos.
+ **Inválido:** uma função durável processa uma mensagem do Amazon SQS, conclui o processamento inicial em 2 minutos e, em seguida, espera 20 minutos por um retorno de chamada externo antes de concluir. Tempo total de execução: 22 minutos. Isso excede o limite de 15 minutos e falhará.
+ **Inválido:** uma função durável processa um registro do Kinesis com várias operações de espera, totalizando 30 minutos entre as etapas. Embora cada invocação individual seja concluída rapidamente, o tempo total de execução excede 15 minutos.

**Importante**  
Configure seu tempo limite de execução durável para 15 minutos ou menos ao usar mapeamentos da origem do evento, caso contrário, a criação do mapeamento da origem do evento falhará. Se seu fluxo de trabalho exigir tempos de execução mais longos, use o padrão de função intermediária descrito abaixo.

## Configuração de mapeamentos da origem do evento
<a name="durable-esm-configuration"></a>

Configure mapeamentos da origem do evento para funções duráveis usando o console do Lambda, a AWS CLI ou SDKs da AWS. Todas as propriedades padrão do mapeamento da origem do evento se aplicam às funções duráveis:

```
aws lambda create-event-source-mapping \
  --function-name arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1 \
  --event-source-arn arn:aws:sqs:us-east-1:123456789012:my-queue \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 5
```

Lembre-se de usar um ARN qualificado (com número de versão ou alias) ao configurar mapeamentos da origem do evento para funções duráveis.

## Tratamento de erros com o mapeamento da origem do evento
<a name="durable-esm-error-handling"></a>

Os mapeamentos da origem do evento fornecem tratamento de erros integrado que funciona com funções duráveis:
+ **Comportamento de novas tentativas:** se a invocação inicial falhar, o mapeamento da origem do evento tentará novamente de acordo com sua configuração de nova tentativa. Configure o máximo de tentativas e intervalos de novas tentativas com base em seus requisitos.
+ **Filas de mensagens não entregues:** configure uma fila de mensagens não entregues para capturar registros que falhem após todas as novas tentativas. Isso evita a perda de mensagens e permite a inspeção manual de registros com falha.
+ **Falhas parciais de lotes:** para o Amazon SQS e o Kinesis, use relatórios de falhas parciais de lotes para processar registros individualmente e somente repetir os registros com falha.
+ **bissecção em erros:** para o Kinesis e DynamoDB Streams, habilite a bissecção em caso de erro para dividir lotes com falha e isolar registros problemáticos.

**nota**  
As funções duráveis oferecem suporte a filas de mensagens não entregues (DLQs) para tratamento de erros, mas não oferecem suporte a destinos do Lambda. Configure uma DLQ para capturar registros de invocações com falhas.

Para obter informações completas sobre o tratamento de erros de mapeamento da origem do evento, consulte [mapeamentos da origem do evento](invocation-eventsourcemapping.md).

## Uso de uma função intermediária para fluxos de trabalho de longa duração
<a name="durable-esm-intermediary-function"></a>

Se seu fluxo de trabalho exigir mais de 15 minutos para ser concluído, use uma função do Lambda padrão intermediária entre o mapeamento da origem do evento e a sua função durável. A função intermediária receberá eventos do mapeamento da origem do evento e invocará a função durável de forma assíncrona, removendo o limite de execução de 15 minutos.

Esse padrão separa o modelo de invocação síncrona do mapeamento da origem do evento do modelo de execução de longa duração da função durável. O mapeamento da origem do evento invoca a função intermediária, que retornará rapidamente após iniciar a execução durável. A função durável então funcionará de forma independente pelo tempo necessário (até 1 ano).

### Arquitetura
<a name="durable-esm-intermediary-architecture"></a>

O padrão da função intermediária usa três componentes:

1. **Mapeamento da origem do evento:** sonda a origem do evento (Amazon SQS, Kinesis, DynamoDB Streams) e invoca a função intermediária de forma síncrona com lotes de registros.

1. **Função intermediária:** uma função do Lambda padrão que recebe eventos do mapeamento da origem do evento, valida e transforma os dados, se necessário, e invoca a função durável de forma assíncrona. Essa função é concluída rapidamente (normalmente em menos de 1 segundo) e retorna o controle para o mapeamento da origem do evento.

1. **Função durável:** processa o evento com uma lógica complexa de várias etapas que pode ser executada por longos períodos. É invocada de forma assíncrona, portanto, não é limitada pelo limite de 15 minutos.

### Implementação
<a name="durable-esm-intermediary-implementation"></a>

A função intermediária receberá o evento inteiro do mapeamento da origem do evento e invocará a função durável de forma assíncrona. Use o parâmetro do nome da execução para garantir que a execução com idempotência seja iniciada, evitando o processamento duplicado se o mapeamento da origem do evento tentar novamente:

------
#### [ TypeScript ]

```
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
import { SQSEvent } from 'aws-lambda';
import { createHash } from 'crypto';

const lambda = new LambdaClient({});

export const handler = async (event: SQSEvent) => {
  // Invoke durable function asynchronously with execution name
  await lambda.send(new InvokeCommand({
    FunctionName: 'arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
    InvocationType: 'Event',
    Payload: JSON.stringify({
      executionName: event.Name,
      event: event
    })
  }));
  
  return { statusCode: 200 };
};
```

------
#### [ Python ]

```
import boto3
import json
import hashlib

lambda_client = boto3.client('lambda')

def handler(event, context):  
    # Invoke durable function asynchronously with execution name
    lambda_client.invoke(
        FunctionName='arn:aws:lambda:us-east-1:123456789012:function:my-durable-function:1',
        InvocationType='Event',
        Payload=json.dumps({
            'executionName': execution_name,
            'event': event["name"]
        })
    )
    
    return {'statusCode': 200}
```

------

Para obter idempotência na própria função intermediária, use o [Powertools para AWS Lambda](https://docs.aws.amazon.com//powertools/) para evitar invocações duplicadas da função durável se o mapeamento da origem do evento tentar novamente a função intermediária.

A função durável receberá a carga com o nome da execução e processará todos os registros com uma lógica de longa duração:

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';

export const handler = withDurableExecution(
  async (payload: any, context: DurableContext) => {
    const sqsEvent = payload.event;
    
    // Process each record with complex, multi-step logic
    const results = await context.map(
      sqsEvent.Records,
      async (ctx, record) => {
        const validated = await ctx.step('validate', async () => {
          return validateOrder(JSON.parse(record.body));
        });
        
        // Wait for external approval (could take hours or days)
        const approval = await ctx.waitForCallback(
          'approval',
          async (callbackId) => {
            await requestApproval(callbackId, validated);
          },
          { timeout: { hours: 48 } }
        );
        
        // Complete processing
        return await ctx.step('complete', async () => {
          return completeOrder(validated, approval);
        });
      }
    );
    
    return { statusCode: 200, processed: results.getResults().length };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
from aws_durable_execution_sdk_python.config import Duration, WaitForCallbackConfig
from collections.abc import Sequence
import json

def validate_order(order_data: dict) -> dict:
    """Validate order data - always passes."""
    return order_data

def request_approval(callback_id: str, validated_order: dict) -> None:
    """Request approval for the order - always passes."""
    pass

def complete_order(validated_order: dict, approval_result: str) -> dict:
    """Complete the order processing - always passes."""
    return validated_order

@durable_execution
def lambda_handler(payload, context: DurableContext):
    sqs_event = payload['event']

    def process_record(
        ctx: DurableContext, 
        record: dict, 
        index: int, 
        items: Sequence[dict]
    ) -> dict:
        validated = ctx.step(
            lambda _: validate_order(json.loads(record['body'])),
            name=f'validate-{index}'
        )

        approval = ctx.wait_for_callback(
            submitter=lambda callback_id, wait_ctx: request_approval(callback_id, validated),
            name=f'approval-{index}',
            config=WaitForCallbackConfig(timeout=Duration.from_seconds(172800))
        )

        return ctx.step(
            lambda _: complete_order(validated, approval),
            name=f'complete-{index}'
        )

    results = context.map(
        inputs=sqs_event['Records'],
        func=process_record,
        name='process-records'
    )

    return {
        'statusCode': 200, 
        'started': results.started_count,
        'completed': results.success_count,
        'failed': results.failure_count,
        'total': results.total_count
    }
```

------

### Considerações importantes
<a name="durable-esm-intermediary-tradeoffs"></a>

Esse padrão remove o limite de execução de 15 minutos ao desacoplar o mapeamento da origem do evento da execução durável. A função intermediária retornará imediatamente após iniciar a execução durável, permitindo que o mapeamento da origem do evento continue sendo processado. A função durável então funcionará de forma independente pelo tempo necessário.

A função intermediária terá êxito quando invocar a função durável, não quando a execução durável for concluída. Se a execução durável falhar posteriormente, o mapeamento da origem do evento não será repetido porque ele já processou o lote com êxito. Implemente o tratamento de erros na função durável e configure filas de mensagens não entregues para execuções com falha.

Use o parâmetro do nome da execução para garantir o início da execução com idempotência. Se o mapeamento da origem do evento tentar novamente a função intermediária, a função durável não iniciará uma execução duplicada porque o nome da execução já existe.

## Origens de eventos com suporte
<a name="durable-esm-supported-sources"></a>

As funções duráveis oferecem suporte a todas as origens de eventos do Lambda que usem mapeamentos da origem do evento:
+ Filas do Amazon SQS (padrão e FIFO)
+ Streams do Kinesis
+ DynamoDB Streams
+ Amazon Managed Streaming for Apache Kafka (Amazon MSK)
+ Apache Kafka autogerenciado
+ Amazon MQ (ActiveMQ e RabbitMQ)
+ Fluxos de mudança do Amazon DocumentDB

Todos os tipos de origens de eventos estão sujeitos ao limite de execução durável de 15 minutos ao invocar funções duráveis.

# Novas tentativas para funções duráveis do Lambda
<a name="durable-execution-sdk-retries"></a>

As funções duráveis fornecem recursos de novas tentativas automáticas que tornam suas aplicações resilientes a falhas transitórias. O SDK lida com novas tentativas em dois níveis: novas tentativas de etapas para falhas na lógica de negócios e novas tentativas de backend em caso de falhas de infraestrutura.

## Novas tentativas de etapa
<a name="durable-step-retries"></a>

Quando ocorre uma exceção não detectada em uma etapa, o SDK faz uma nova tentativa da etapa automaticamente com base na estratégia de novas tentativas configurada. As novas tentativas de etapas são operações com pontos de verificação que permitem que o SDK suspenda a execução e continue posteriormente sem perder o andamento.

### Comportamento de novas tentativas de etapa
<a name="durable-step-retry-behavior"></a>

A tabela a seguir descreve como o SDK lida com exceções em etapas:


| Cenário | O que acontece | Medição de impacto | 
| --- | --- | --- | 
| Exceção em etapa com novas tentativas restantes | O SDK cria um ponto de verificação para a nova tentativa e suspende a função. Na próxima invocação, a etapa sofre nova tentativa com o retardo de recuo configurado. | 1 operação \$1 tamanho da carga útil de erro | 
| Exceção em etapa sem novas tentativas restantes | A etapa falha e emite uma exceção. Se o seu código do manipulador não capturar essa exceção, toda a execução falhará. | 1 operação \$1 tamanho da carga útil de erro | 

Quando uma etapa precisa ser repetida, o SDK verifica o estado de novas tentativas e sai da invocação do Lambda se nenhum outro trabalho estiver em execução. Isso permite que o SDK implemente retardos de recuo sem consumir recursos computacionais. A função é retomada automaticamente após o período de recuo.

### Configuração de estratégias de novas tentativas de etapas
<a name="durable-step-retry-configuration"></a>

Configure estratégias de novas tentativas para controlar como as etapas tratam as falhas. É possível especificar o máximo de tentativas, os intervalos de recuo e as condições para novas tentativas.

**Recuo exponencial com o máximo de tentativas:**

------
#### [ TypeScript ]

```
const result = await context.step('call-api', async () => {
  const response = await fetch('https://api.example.com/data');
  if (!response.ok) throw new Error(`API error: ${response.status}`);
  return await response.json();
}, {
  retryStrategy: (error, attemptCount) => {
    if (attemptCount >= 5) {
      return { shouldRetry: false };
    }
    // Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s)
    const delay = Math.min(2 * Math.pow(2, attemptCount - 1), 300);
    return { shouldRetry: true, delay: { seconds: delay } };
  }
});
```

------
#### [ Python ]

```
def retry_strategy(error, attempt_count):
    if attempt_count >= 5:
        return {'should_retry': False}
    # Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s)
    delay = min(2 * (2 ** (attempt_count - 1)), 300)
    return {'should_retry': True, 'delay': delay}

result = context.step(
    lambda _: call_external_api(),
    name='call-api',
    config=StepConfig(retry_strategy=retry_strategy)
)
```

------

**Recuo com intervalo fixo:**

------
#### [ TypeScript ]

```
const orders = await context.step('query-orders', async () => {
  return await queryDatabase(event.userId);
}, {
  retryStrategy: (error, attemptCount) => {
    if (attemptCount >= 3) {
      return { shouldRetry: false };
    }
    return { shouldRetry: true, delay: { seconds: 5 } };
  }
});
```

------
#### [ Python ]

```
def retry_strategy(error, attempt_count):
    if attempt_count >= 3:
        return {'should_retry': False}
    return {'should_retry': True, 'delay': 5}

orders = context.step(
    lambda _: query_database(event['userId']),
    name='query-orders',
    config=StepConfig(retry_strategy=retry_strategy)
)
```

------

**Nova tentativa condicional (tentar novamente somente erros específicos):**

------
#### [ TypeScript ]

```
const result = await context.step('call-rate-limited-api', async () => {
  const response = await fetch('https://api.example.com/data');
  
  if (response.status === 429) throw new Error('RATE_LIMIT');
  if (response.status === 504) throw new Error('TIMEOUT');
  if (!response.ok) throw new Error(`API_ERROR_${response.status}`);
  
  return await response.json();
}, {
  retryStrategy: (error, attemptCount) => {
    // Only retry rate limits and timeouts
    const isRetryable = error.message === 'RATE_LIMIT' || error.message === 'TIMEOUT';
    
    if (!isRetryable || attemptCount >= 3) {
      return { shouldRetry: false };
    }
    
    // Exponential backoff: 1s, 2s, 4s (capped at 30s)
    const delay = Math.min(Math.pow(2, attemptCount - 1), 30);
    return { shouldRetry: true, delay: { seconds: delay } };
  }
});
```

------
#### [ Python ]

```
def retry_strategy(error, attempt_count):
    # Only retry rate limits and timeouts
    is_retryable = str(error) in ['RATE_LIMIT', 'TIMEOUT']
    
    if not is_retryable or attempt_count >= 3:
        return {'should_retry': False}
    
    # Exponential backoff: 1s, 2s, 4s (capped at 30s)
    delay = min(2 ** (attempt_count - 1), 30)
    return {'should_retry': True, 'delay': delay}

result = context.step(
    lambda _: call_rate_limited_api(),
    name='call-rate-limited-api',
    config=StepConfig(retry_strategy=retry_strategy)
)
```

------

**Desativar novas tentativas:**

------
#### [ TypeScript ]

```
const isDuplicate = await context.step('check-duplicate', async () => {
  return await checkIfOrderExists(event.orderId);
}, {
  retryStrategy: () => ({ shouldRetry: false })
});
```

------
#### [ Python ]

```
is_duplicate = context.step(
    lambda _: check_if_order_exists(event['orderId']),
    name='check-duplicate',
    config=StepConfig(
        retry_strategy=lambda error, attempt: {'should_retry': False}
    )
)
```

------

Quando a estratégia de novas tentativas retorna `shouldRetry: false`, a etapa falha imediatamente sem novas tentativas. Use isso para operações que não devam ser repetidas, como verificações de idempotência ou operações com efeitos colaterais que não possam ser repetidos com segurança.

## Exceções fora das etapas
<a name="durable-handler-exceptions"></a>

Quando ocorre uma exceção não detectada no código do manipulador, mas fora de qualquer etapa, o SDK marca a execução como com falha. Isso garante que os erros na lógica da aplicação sejam capturados e relatados adequadamente.


| Cenário | O que acontece | Medição de impacto | 
| --- | --- | --- | 
| Exceção no código do manipulador fora de qualquer etapa | O SDK marca a execução como COM FALHA e retorna o erro. A exceção não sofre nova tentativa automaticamente. | Tamanho da carga útil de erro | 

Para habilitar a nova tentativa automática para código propenso a erros, encapsule-o em uma etapa com uma estratégia de nova tentativa. As etapas fornecem uma nova tentativa automática com recuo configurável, enquanto as etapas externas do código falham imediatamente.

## Novas tentativas de backend
<a name="durable-backend-retries"></a>

As novas tentativas de backend ocorrem quando o Lambda encontra falhas de infraestrutura, erros de runtime ou quando o SDK não consegue se comunicar com o serviço de execução durável. O Lambda faz uma nova tentativa dessas falhas automaticamente para ajudar suas funções duráveis a se recuperarem de problemas transitórios de infraestrutura.

### Cenários de nova tentativa de backend
<a name="durable-backend-retry-scenarios"></a>

O Lambda faz uma nova tentativa da sua função automaticamente quando encontra os cenários a seguir:
+ **Erros de serviço internos**: quando o Lambda ou o serviço de execução durável retorna um erro 5xx, indicando um problema temporário no serviço.
+ **Limitação**: quando sua função sofre controle de utilização devido a limites de simultaneidade ou cotas de serviço.
+ **Tempos limite**: quando o SDK não consegue alcançar o serviço de execução durável dentro do período de tempo limite.
+ **Falhas na inicialização da sandbox**: quando o Lambda não consegue inicializar o ambiente de execução.
+ **Erros de runtime**: quando o runtime do Lambda encontra erros fora do seu código de função, como erros de falta de memória ou falhas no processo.
+ **Erros de token de ponto de verificação inválido**: quando o token de ponto de verificação não é mais válido, normalmente devido a mudanças de estado do lado do serviço.

A tabela a seguir descreve como o SDK trata esses cenários.


| Cenário | O que acontece | Medição de impacto | 
| --- | --- | --- | 
| Erro de runtime fora do manipulador durável (OOM, tempo limite, falha) | O Lambda automaticamente faz uma nova tentativa de invocação. O SDK é reproduzido a partir do último ponto de verificação, ignorando as etapas concluídas. | Tamanho da carga útil de erro \$1 1 operação por nova tentativa | 
| Erro de serviço (5xx) ou tempo limite ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState | O Lambda automaticamente faz uma nova tentativa de invocação. O SDK reproduz a partir do último ponto de verificação. | Tamanho da carga útil de erro \$1 1 operação por nova tentativa | 
| Controle de utilização (429) ou token de ponto de verificação inválido ao chamar as APIs CheckpointDurableExecution / GetDurableExecutionState | O Lambda automaticamente faz uma nova tentativa de invocação com recuo exponencial. O SDK reproduz a partir do último ponto de verificação. | Tamanho da carga útil de erro \$1 1 operação por nova tentativa | 
| Erro do cliente (4xx, exceto 429 e token inválido) quando as APIs CheckpointDurableExecution / GetDurableExecutionState | O SDK marca a execução como COM FALHA. Nenhuma nova tentativa automática ocorre porque o erro indica um problema permanente. | Tamanho da carga útil de erro | 

As novas tentativas de backend usam o recuo exponencial e prosseguem até que a função tenha êxito ou o tempo limite de execução seja atingido. Durante a reprodução, o SDK ignora os pontos de verificação concluídos e continua a execução da última operação com êxito, garantindo que sua função não reexecute o trabalho concluído.

## Práticas recomendadas de novas tentativas
<a name="durable-retry-best-practices"></a>

Siga estas práticas recomendadas ao configurar estratégias de novas tentativas:
+ **Configure estratégias de novas tentativas explícitas**: não confie no comportamento padrão de novas tentativas na produção. Configure estratégias de novas tentativas explícitas com o máximo de tentativas e intervalos de recuo apropriados para seu caso de uso.
+ **Use novas tentativas condicionais**: - implemente a lógica `shouldRetry` para repetir somente erros transitórios (limites de taxa, tempos limite) e antecipe-se à falha em erros permanentes (falhas de validação, não encontrado).
+ **Defina o máximo de tentativas apropriadas**: equilíbrio entre resiliência e tempo de execução. Muitas tentativas podem atrasar a detecção de falhas, enquanto poucas podem causar falhas desnecessárias.
+ **Use o recuo exponencial**: o recuo exponencial reduz a carga nos serviços subsequentes e aumenta a probabilidade de recuperação de falhas transitórias.
+ **Encapsule o código propenso a erros em etapas**: o código fora das etapas não pode sofrer novas tentativas automaticamente. Encapsule chamadas externas de API, consultas de banco de dados e outras operações sujeitas a erros em etapas com estratégias de novas tentativas.
+ **Monitore as métricas de novas tentativas**: acompanhe as operações de novas tentativas de etapas e falhas de execução no Amazon CloudWatch para identificar padrões e otimizar estratégias de novas tentativas.

# Potência igual
<a name="durable-execution-idempotency"></a>

As funções duráveis fornecem idempotência integrada para o início da execução por meio de nomes de execução. Quando você fornece um nome de execução, o Lambda o usa para evitar execuções duplicadas e permitir novas tentativas seguras de solicitações de invocação. Por padrão, as etapas têm semântica de execução de pelo menos uma vez. Durante a reprodução, o SDK retorna resultados verificados sem reexecutar as etapas concluídas, mas sua lógica de negócios deve ter idempotência para lidar com possíveis novas tentativas antes da conclusão.

**nota**  
Os mapeamentos da origem do evento (ESM) do Lambda não oferecem suporte à idempotência na inicialização. Portanto, cada invocação (incluindo novas tentativas) inicia uma nova execução durável. Para garantir a execução com idempotência com mapeamentos da origem do evento, implemente a lógica de idempotência em seu código de função, como com o [Powertools para AWS Lambda](https://docs.aws.amazon.com//powertools/) use uma função do Lambda comum como proxy (despachante) para invocar uma função durável com uma chave de idempotência (parâmetro do nome da execução).

## Nomes de execuções
<a name="durable-idempotency-execution-names"></a>

É possível fornecer um nome de execução ao invocar uma função durável. O nome da execução atua como uma chave de idempotência, permitindo que você repita com segurança as solicitações de invocação sem criar execuções duplicadas. Se você não fornecer um nome, o Lambda gerará automaticamente um ID de execução exclusivo.

Os nomes de execução deves ser exclusivos na sua conta e na sua região atual. Quando você invoca uma função com um nome de execução que já existe, o comportamento do Lambda depende do estado da execução existente e da correspondência da carga útil.

## Comportamento de idempotência
<a name="durable-idempotency-behavior"></a>

A tabela a seguir descreve como o Lambda lida com solicitações de invocação com base no fato de você fornecer um nome de execução, no estado de execução existente e na correspondência da carga útil:


| Cenário | Nome fornecido? | Status de execução existente | Carga útil idêntica? | Comportamento | 
| --- | --- | --- | --- | --- | 
| 1 | Não | N/D | N/D | Nova execução iniciada: o Lambda gera um ID de execução exclusivo e inicia uma nova execução | 
| 2 | Sim | Nunca existiu ou a retenção expirou | N/D | Nova execução iniciada: o Lambda inicia uma nova execução com o nome fornecido | 
| 3 | Sim | Executar | Sim | Início com idempotência: o Lambda retorna as informações de execução existentes sem iniciar uma duplicata. Para invocações síncronas, isso atua como uma reconexão com a execução em andamento | 
| 4 | Sim | Executar | Não | Erro: o Lambda retorna um erro DurableExecutionAlreadyExists porque uma execução com esse nome já está em andamento com uma carga útil diferente | 
| 5 | Sim | Fechado (com êxito, com falha, interrompido ou atingiu o tempo limite) | Sim | Início com idempotência: o Lambda retorna as informações de execução existentes sem iniciar uma nova execução. O resultado da execução fechada é retornado | 
| 6 | Sim | Fechado (com êxito, com falha, interrompido ou atingiu o tempo limite) | Não | Erro: o Lambda retorna um erro DurableExecutionAlreadyExists porque uma execução com esse nome já foi concluída com uma carga útil diferente | 

**Observação**  
Os cenários 3 e 5 demonstram um comportamento com idempotência em que o Lambda lida com segurança com solicitações de invocação duplicadas, retornando as informações de execução existentes em vez de criar duplicatas.

## Idempotência de etapas
<a name="durable-idempotency-steps"></a>

Por padrão, as etapas têm semântica de execução de ao menos uma vez. Quando sua função é reproduzida após uma espera, um retorno de chamada ou uma falha, o SDK compara cada etapa com base no log do ponto de verificação. Para etapas que já foram concluídas, o SDK retorna o resultado do checkpoint sem reexecutar a lógica da etapa. No entanto, se uma etapa falhar ou a função for interrompida antes da conclusão da etapa, a etapa poderá ser executada várias vezes.

Sua lógica de negócios encapsulada em etapas deve ter idempotência para lidar com possíveis novas tentativas. Use chaves de idempotência para garantir que operações como pagamentos ou gravações de banco de dados sejam executadas somente uma vez, mesmo que a etapa sofra uma nova tentativa.

**Exemplo: uso de chaves de idempotência em etapas**

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
import { randomUUID } from 'crypto';

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Generate idempotency key once
    const idempotencyKey = await context.step('generate-key', async () => {
      return randomUUID();
    });
    
    // Use idempotency key in payment API to prevent duplicate charges
    const payment = await context.step('process-payment', async () => {
      return paymentAPI.charge({
        amount: event.amount,
        idempotencyKey: idempotencyKey
      });
    });
    
    return { statusCode: 200, payment };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
import uuid

@durable_execution
def handler(event, context: DurableContext):
    # Generate idempotency key once
    idempotency_key = context.step(
        lambda _: str(uuid.uuid4()),
        name='generate-key'
    )
    
    # Use idempotency key in payment API to prevent duplicate charges
    payment = context.step(
        lambda _: payment_api.charge(
            amount=event['amount'],
            idempotency_key=idempotency_key
        ),
        name='process-payment'
    )
    
    return {'statusCode': 200, 'payment': payment}
```

------

É possível configurar etapas para usar a semântica de execução de no máximo uma vez definindo o modo de execução como `AT_MOST_ONCE_PER_RETRY`. Isso garante que a etapa seja executada no máximo uma vez por nova tentativa, mas pode não ser executada se a função for interrompida antes da conclusão da etapa.

O SDK impõe a reprodução determinística ao validar se os nomes e a ordem das etapas correspondem ao log do ponto de verificação durante a reprodução. Se seu código tentar executar etapas em uma ordem diferente ou com nomes diferentes, o SDK emitirá um `NonDeterministicExecutionError`

**Como a reprodução funciona com etapas concluídas:**

1. Primeira invocação: a função executa a etapa A, cria o ponto de verificação e aguarda

1. Segunda invocação (após a espera): a função é reproduzida desde o início, a etapa A retorna o resultado do ponto de verificação instantaneamente sem reexecução e, em seguida, prossegue até a etapa B

1. Terceira invocação (após outra espera): a função é reproduzida desde o início, as etapas A e B retornam os resultados marcados instantaneamente e, em seguida, prossegue até a etapa C

Esse mecanismo de reprodução garante que as etapas concluídas não sejam reexecutadas, mas sua lógica de negócios ainda deve ter idempotência para lidar com novas tentativas antes da conclusão.

# Testes de funções duráveis do Lambda
<a name="durable-testing"></a>

A AWS fornece SDKs de teste dedicados para funções duráveis que permitem executar e inspecionar execuções localmente e na nuvem. Instale o SDK de teste para a sua linguagem:

------
#### [ TypeScript ]

```
npm install --save-dev @aws/aws-durable-execution-sdk-js-testing
```

Para obter a documentação completa e exemplos, consulte [SDK de testes de TypeScript](https://github.com/aws/aws-durable-execution-sdk-js/tree/development/packages/aws-durable-execution-sdk-js-testing) no GitHub.

------
#### [ Python ]

```
pip install aws-durable-execution-sdk-python-testing
```

Para obter a documentação completa e exemplos, consulte [SDK de testes de Python ](https://github.com/aws/aws-durable-execution-sdk-python-testing) no GitHub.

------

O SDK de testes fornece dois modos de teste: o teste local, para testes de unidade rápidos, e o teste em nuvem, para testes de integração com funções implantadas.

## Teste local
<a name="durable-local-testing"></a>

O teste local executa suas funções duráveis no seu ambiente de desenvolvimento sem exigir recursos implantados. O executor de testes executa seu código de função diretamente e captura todas as operações para inspeção.

Use testes locais para testes de unidade, desenvolvimento orientado a testes e pipelines de CI/CD. Os testes são executados localmente, sem latência de rede ou custos adicionais.

**Exemplo de teste:**

------
#### [ TypeScript ]

```
import { withDurableExecution } from '@aws/aws-durable-execution-sdk-js';
import { DurableFunctionTestRunner } from '@aws/aws-durable-execution-sdk-js-testing';

const handler = withDurableExecution(async (event, context) => {
  const result = await context.step('calculate', async () => {
    return event.a + event.b;
  });
  return result;
});

test('addition works correctly', async () => {
  const runner = new DurableFunctionTestRunner({ handler });
  const result = await runner.run({ a: 5, b: 3 });
  
  expect(result.status).toBe('SUCCEEDED');
  expect(result.result).toBe(8);
  
  const step = result.getStep('calculate');
  expect(step.result).toBe(8);
});
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
from aws_durable_execution_sdk_python_testing import DurableFunctionTestRunner
from aws_durable_execution_sdk_python.execution import InvocationStatus

@durable_execution
def handler(event: dict, context: DurableContext) -> int:
    result = context.step(lambda _: event["a"] + event["b"], name="calculate")
    return result

def test_addition():
    runner = DurableFunctionTestRunner(handler=handler)
    with runner:
        result = runner.run(input={"a": 5, "b": 3}, timeout=10)
    
    assert result.status is InvocationStatus.SUCCEEDED
    assert result.result == 8
    
    step = result.get_step("calculate")
    assert step.result == 8
```

------

O executor de teste captura o estado de execução, incluindo o resultado final, os resultados de etapas individuais, as operações de espera, os retornos de chamada e quaisquer erros. É possível inspecionar as operações por nome ou percorrer todas as operações para verificar o comportamento da execução.

### Armazenamentos de execução
<a name="durable-execution-stores"></a>

O SDK de teste usa armazenamentos de execução para manter os dados de execução do teste. Por padrão, os testes usam um armazenamento na memória que é rápido e não requer limpeza. Para depurar ou analisar o histórico de execução, é possível usar um armazenamento do sistema de arquivos que salva as execuções como arquivos JSON.

**Armazenamento na memória (padrão):**

O armazenamento na memória mantém os dados de execução na memória durante as execuções de teste. Os dados são perdidos quando os testes são concluídos, tornando-os ideais para testes de unidade padrão e pipelines de CI/CD, nos quais não é preciso inspecionar as execuções após a conclusão dos testes.

**Armazenamento do sistema de arquivos:**

O armazenamento do sistema de arquivos persiste os dados de execução no disco como arquivos JSON. Cada execução é salva em um arquivo separado, facilitando a inspeção do histórico de execução após a conclusão dos testes. Use o armazenamento do sistema de arquivos ao depurar falhas de teste complexas ou ao analisar padrões de execução ao longo do tempo.

Configure o armazenamento usando variáveis de ambiente:

```
# Use filesystem store
export AWS_DEX_STORE_TYPE=filesystem
export AWS_DEX_STORE_PATH=./test-executions

# Run tests
pytest tests/
```

Os arquivos de execução são armazenados com nomes higienizados e contêm o estado completo da execução, incluindo operações, pontos de verificação e resultados. O armazenamento do sistema de arquivo criará automaticamente o diretório de armazenamento se ele não existir.

## Teste na nuvem
<a name="durable-cloud-testing"></a>

O teste em nuvem invoca funções duráveis implantadas na AWS e recupera seu histórico de execução usando a API do Lambda. Use os testes em nuvem para verificar o comportamento em ambientes de produção com serviços da AWS e configurações reais.

O teste na nuvem exige uma função implantada e credenciais da AWS com permissões para invocar funções e ler o histórico de execução:

```
{
    "Version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction",
                "lambda:GetDurableExecution",
                "lambda:GetDurableExecutionHistory"
            ],
            "Resource": "arn:aws:lambda:region:account-id:function:function-name"
        }
    ]
}
```

**Exemplo de teste de nuvem:**

------
#### [ TypeScript ]

```
import { DurableFunctionCloudTestRunner } from '@aws/aws-durable-execution-sdk-js-testing';

test('deployed function processes orders', async () => {
  const runner = new DurableFunctionCloudTestRunner({
    functionName: 'order-processor',
    region: 'us-east-1'
  });
  
  const result = await runner.run({ orderId: 'order-123' });
  
  expect(result.status).toBe('SUCCEEDED');
  expect(result.result.status).toBe('completed');
});
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python_testing import (
    DurableFunctionCloudTestRunner,
    DurableFunctionCloudTestRunnerConfig
)

def test_deployed_function():
    config = DurableFunctionCloudTestRunnerConfig(
        function_name="order-processor",
        region="us-east-1"
    )
    runner = DurableFunctionCloudTestRunner(config=config)
    
    result = runner.run(input={"orderId": "order-123"})
    
    assert result.status is InvocationStatus.SUCCEEDED
    assert result.result["status"] == "completed"
```

------

Os testes de nuvem invocam a função real implantada e recuperam o histórico de execução da AWS. Isso permite verificar a integração com outros serviços da AWS, validar as características de performance e testar com dados e configurações semelhantes aos de produção.

## O que testar
<a name="durable-testing-patterns"></a>

Teste as funções duráveis verificando os resultados da execução, o comportamento da operação e o tratamento de erros. Concentre-se na correção da lógica de negócios em vez de nos detalhes da implementação.

**Verifique os resultados da execução:** confira se as funções retornam os valores esperados para determinadas entradas. Teste as execuções com êxito e os casos de erro para garantir que as funções tratem entradas inválidas de forma adequada.

**Inspecione a execução da operação:** verifique se as etapas, esperas e retornos de chamada são executados conforme o esperado. Verifique os resultados das etapas para garantir que as operações intermediárias produzam valores corretos. Valide se as operações de espera estão configuradas com tempos limite apropriados e se os retornos de chamada foram criados com as configurações corretas.

**Tratamento de erros de teste:** verifique se as funções falham corretamente com mensagens de erro descritivas quando recebem uma entrada inválida. Teste o comportamento de novas tentativas simulando falhas transitórias e confirmando as novas tentativas adequadas das operações. Verifique se falhas permanentes não acionam novas tentativas desnecessárias.

**Valide os fluxos de trabalho:** para fluxos de trabalho de várias etapas, verifique se as operações são executadas na ordem correta. Teste a ramificação condicional para garantir que diferentes caminhos de execução funcionem corretamente. Valide operações paralelas executadas simultaneamente e produza os resultados esperados.

Os repositórios de documentação do SDK contêm exemplos abrangentes de padrões de teste, incluindo fluxos de trabalho de várias etapas, cenários de erro, tratamento de tempo limite e padrões de sondagens.

## Estratégia de teste
<a name="durable-testing-strategy"></a>

Use testes locais para testes de unidade durante o desenvolvimento e em pipelines de CI/CD. Os testes locais são executados rapidamente, não exigem credenciais da AWS e fornecem feedback imediato sobre alterações no código. Escreva testes locais para verificar a lógica de negócios, o tratamento de erros e o comportamento da operação.

Use testes de nuvem para testes de integração antes da implantação na produção. Os testes de nuvem verificam o comportamento com serviços e configurações reais da AWS, validam as características de performance e testam os fluxos de trabalho de ponta a ponta. Execute testes de nuvem em ambientes de preparação para detectar problemas de integração antes que eles cheguem à produção.

Simule dependências externas em testes locais para isolar a lógica da função e manter os testes rápidos. Use testes de nuvem para verificar a integração real com serviços externos, como bancos de dados, APIs e outros serviços da AWS.

Escreva testes focados que verifiquem um comportamento específico. Use nomes de testes descritivos que expliquem o que está sendo testado. Agrupe os testes relacionados e use acessórios de teste para obter um código de configuração comum. Mantenha os testes simples e evite uma lógica de teste complexa que seja difícil de entender.

## Falhas de depuração
<a name="durable-testing-debugging"></a>

Quando os testes falharem, inspecione o resultado da execução para entender o que houve de errado. Verifique o status da execução para ver se a função foi concluída com êxito, falhou ou atingiu o tempo limite. Leia as mensagens de erro para entender a causa da falha.

Inspecione os resultados individuais da operação para descobrir onde o comportamento divergiu das expectativas. Verifique os resultados das etapas para ver quais valores foram produzidos. Verifique a ordem das operações para confirmar as operações executadas na sequência esperada. Conte as operações para garantir que o número certo de etapas, esperas e retornos de chamada tenham sido criados.

Os problemas comuns incluem código não determinístico que produza resultados diferentes nas reproduções, estado compartilhado por meio de variáveis globais que sejam interrompidas durante a reprodução e operações ausentes devido a erros lógicos condicionais. Use depuradores e logs padrão para analisar o código da função e monitorar o fluxo de execução.

Para testes de nuvem, inspecione o histórico de execução no CloudWatch Logs para ver os logs detalhados da operação. Use o rastreamento para acompanhar o fluxo de execução nos serviços e identificar gargalos.

# Monitoramento das funções duráveis
<a name="durable-monitoring"></a>

É possível monitorar suas funções duráveis usando métricas do CloudWatch, CloudWatch Logs e rastreamento. Como as funções duráveis podem ser executadas por longos períodos e abranger várias invocações de funções, monitorá-las exige a compreensão de seus padrões de execução exclusivos, incluindo pontos de verificação, transições de estado e comportamento de novas tentativas.

## métricas do CloudWatch
<a name="durable-monitoring-metrics"></a>

O Lambda publica métricas automaticamente no CloudWatch sem custo adicional. As funções duráveis fornecem métricas adicionais além das métricas padrão do Lambda para ajudá-lo a monitorar fluxos de trabalho de longa duração, o gerenciamento de estados e a utilização de recursos.

### Métricas de execução durável
<a name="durable-monitoring-execution-metrics"></a>

O Lambda emite as métricas a seguir para execuções duráveis:


| Métrica | Descrição | 
| --- | --- | 
| ApproximateRunningDurableExecutions | Número de execuções duráveis no estado EM EXECUÇÃO | 
| ApproximateRunningDurableExecutionsUtilization | Percentual da cota máxima de execuções duráveis em andamento da sua conta atualmente em uso | 
| DurableExecutionDuration | Tempo decorrido de relógio em milissegundos em que uma execução durável permaneceu no estado EM EXECUÇÃO | 
| DurableExecutionStarted | Número de execuções duráveis iniciadas | 
| DurableExecutionStopped | Número de execuções duráveis interrompidas usando a API StopDurableExecution | 
| DurableExecutionSucceeded | Número de execuções duráveis concluídas com êxito. | 
| DurableExecutionFailed | Número de execuções duráveis concluídas com uma falha | 
| DurableExecutionTimedOut | Número de execuções duráveis que excederam seu tempo limite de execução configurado | 
| DurableExecutionOperations | Número cumulativo de operações realizadas em uma execução durável (máximo: 3.000) | 
| DurableExecutionStorageWrittenBytes | Quantidade cumulativa de dados em bytes persistida por uma execução durável (máximo: 100 MB) | 

### métricas do CloudWatch
<a name="durable-monitoring-standard-metrics"></a>

O Lambda emite métricas padrão de invocação, performance e simultaneidade para funções duráveis. Como uma execução durável pode abranger várias invocações de funções à medida que avança pelos pontos de verificação e reproduções, essas métricas se comportam de forma diferente das funções padrão:
+ **Invocações:** conta cada invocação de função, incluindo reproduções. Uma única execução durável pode gerar vários pontos de dados de invocação.
+ **Duração:** mede cada invocação de função separadamente. Use `DurableExecutionDuration` para o tempo total gasto por uma única execução durável.
+ **Erros:** rastreia as falhas de invocação da função. Use `DurableExecutionFailed` para falhas no nível de execução.

Para obter uma lista completa das métricas padrão do Lambda, consulte [Tipos de métricas para funções do Lambda](https://docs.aws.amazon.com//lambda/latest/dg/monitoring-metrics-types.html).

### Criar alarmes do CloudWatch
<a name="durable-monitoring-alarms"></a>

Crie alarmes do CloudWatch para notificá-lo quando as métricas excederem os limites. Alarmes comuns incluem:
+ `ApproximateRunningDurableExecutionsUtilization` excede 80% da sua cota
+ `DurableExecutionFailed` aumenta acima de um limite
+ `DurableExecutionTimedOut` indica que as execuções estão se aproximando do tempo limite
+ `DurableExecutionStorageWrittenBytes` se aproxima dos limites de armazenamento

Para obter mais informações, consulte [Uso de alarmes do CloudWatch](https://docs.aws.amazon.com//AmazonCloudWatch/latest/monitoring/AlarmThatSendsEmail.html).

## Eventos EventBridge
<a name="durable-monitoring-eventbridge"></a>

O Lambda publica eventos duráveis de alteração do status de execução no EventBridge. É possível usar esses eventos para acionar fluxos de trabalho, enviar notificações ou rastrear alterações no ciclo de vida da execução em suas funções duráveis.

### Eventos de alteração de status de execução durável
<a name="durable-eventbridge-status-changes"></a>

O Lambda emite um evento para o EventBridge sempre que uma execução durável muda de status. Esses eventos têm as características a seguir:
+ **Fonte:** `aws.lambda`
+ **Tipo de detalhe:** `Durable Execution Status Change`

Os eventos de alteração de status são publicados para os estados de execução a seguir:
+ `RUNNING`: execução iniciada
+ `SUCCEEDED`: execução concluída com êxito
+ `STOPPED`: execução interrompida usando a API StopDurableExecution
+ `FAILED`: execução com falha com um erro
+ `TIMED_OUT`: execução com tempo limite configurado excedido

O exemplo a seguir mostra um evento de alteração de status de execução durável:

```
{
  "version": "0",
  "id": "d019b03c-a8a3-9d58-85de-241e96206538",
  "detail-type": "Durable Execution Status Change",
  "source": "aws.lambda",
  "account": "123456789012",
  "time": "2025-11-20T13:08:22Z",
  "region": "us-east-1",
  "resources": [],
  "detail": {
    "durableExecutionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:$LATEST/durable-execution/090c4189-b18b-4296-9d0c-cfd01dc3a122/9f7d84c9-ea3d-3ffc-b3e5-5ec51c34ffc9",
    "durableExecutionName": "order-123",
    "functionArn": "arn:aws:lambda:us-east-1:123456789012:function:my-function:2",
    "status": "RUNNING",
    "startTimestamp": "2025-11-20T13:08:22.345Z"
  }
}
```

Para estados terminais (`SUCCEEDED`, `STOPPED`, `FAILED`, `TIMED_OUT`), o evento inclui um campo `endTimestamp` indicando quando a execução foi concluída.

### Criar regras do EventBridge
<a name="durable-eventbridge-rules"></a>

Crie regras para rotear eventos de alteração de status de execução duráveis para destinos como o Amazon Simple Notification Service, Amazon Simple Queue Service ou outras funções do Lambda.

O exemplo a seguir cria uma regra que corresponde a todas as alterações de status de execução durável:

```
{
  "source": ["aws.lambda"],
  "detail-type": ["Durable Execution Status Change"]
}
```

O exemplo a seguir cria uma regra que corresponde somente às execuções com falha:

```
{
  "source": ["aws.lambda"],
  "detail-type": ["Durable Execution Status Change"],
  "detail": {
    "status": ["FAILED"]
  }
}
```

O exemplo a seguir cria uma regra que corresponde às alterações de status de uma função específica:

```
{
  "source": ["aws.lambda"],
  "detail-type": ["Durable Execution Status Change"],
  "detail": {
    "functionArn": [{
      "prefix": "arn:aws:lambda:us-east-1:123456789012:function:my-function"
    }]
  }
}
```

Para obter mais informações sobre a criação de regras, consulte os [tutoriais do Amazon EventBridge](https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-tutorial.html) no Guia do usuário do EventBridge.

## AWS X-RayRastreamento do
<a name="durable-monitoring-xray"></a>

É possível habilitar o rastreamento do X-Ray em suas funções duráveis. O Lambda passa o cabeçalho de rastreamento do X-Ray para a execução durável, permitindo que você rastreie solicitações em todo o seu fluxo de trabalho.

Para habilitar o rastreamento do X-Ray usando o console do Lambda, escolha sua função, escolha as ferramentas de configuração, monitoramento e operações e habilite o Rastreamento ativo no X-Ray.

Como habilitar o rastreamento do X-Ray usando a AWS CLI.

```
aws lambda update-function-configuration \
    --function-name my-durable-function \
    --tracing-config Mode=Active
```

Para habilitar o rastreamento do AWS X-Ray usando o AWS SAM:

```
Resources:
  MyDurableFunction:
    Type: AWS::Serverless::Function
    Properties:
      Tracing: Active
      DurableConfig:
        ExecutionTimeout: 3600
```

Para obter mais informações sobre o X-Ray, consulte o [Guia do desenvolvedor do AWS X-Ray](https://docs.aws.amazon.com//xray/latest/devguide/aws-xray.html).

# Práticas recomendadas para funções duráveis do Lambda
<a name="durable-best-practices"></a>

As funções duráveis usam um modelo de execução baseado em reprodução que exige padrões diferentes das funções do Lambda tradicionais. Siga essas melhores práticas para criar fluxos de trabalho confiáveis e econômicos.

## Escreva código determinístico
<a name="durable-determinism"></a>

Durante a reprodução, sua função é executada desde o início e deve seguir o mesmo caminho de execução da execução original. O código fora das operações duráveis deve ser determinístico, produzindo os mesmos resultados com as mesmas entradas.

**Encapsule as operações não determinísticas em etapas:**
+ Geração de números aleatórios e UUIDs
+ Hora atual ou timestamps
+ Chamadas de API externas e consultas de banco de dados
+ Operações do sistema de arquivos

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';
import { randomUUID } from 'crypto';

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Generate transaction ID inside a step
    const transactionId = await context.step('generate-transaction-id', async () => {
      return randomUUID();
    });
    
    // Use the same ID throughout execution, even during replay
    const payment = await context.step('process-payment', async () => {
      return processPayment(event.amount, transactionId);
    });
    
    return { statusCode: 200, transactionId, payment };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
import uuid

@durable_execution
def handler(event, context: DurableContext):
    # Generate transaction ID inside a step
    transaction_id = context.step(
        lambda _: str(uuid.uuid4()),
        name='generate-transaction-id'
    )
    
    # Use the same ID throughout execution, even during replay
    payment = context.step(
        lambda _: process_payment(event['amount'], transaction_id),
        name='process-payment'
    )
    
    return {'statusCode': 200, 'transactionId': transaction_id, 'payment': payment}
```

------

**Importante**  
Não use variáveis globais ou fechamentos para compartilhar o estado entre as etapas. Passe dados por meio de valores de retorno. O estado global é interrompido durante a reprodução, pois as etapas retornam resultados em cache, mas as variáveis globais são redefinidas.

**Evite mutações de encerramento:** as variáveis capturadas em fechamentos podem perder mutações durante a reprodução. As etapas retornam resultados em cache, mas as atualizações de variáveis fora da etapa não são reproduzidas.

------
#### [ TypeScript ]

```
// ❌ WRONG: Mutations lost on replay
export const handler = withDurableExecution(async (event, context) => {
  let total = 0;
  
  for (const item of items) {
    await context.step(async () => {
      total += item.price; // ⚠️ Mutation lost on replay!
      return saveItem(item);
    });
  }
  
  return { total }; // Inconsistent value!
});

// ✅ CORRECT: Accumulate with return values
export const handler = withDurableExecution(async (event, context) => {
  let total = 0;
  
  for (const item of items) {
    total = await context.step(async () => {
      const newTotal = total + item.price;
      await saveItem(item);
      return newTotal; // Return updated value
    });
  }
  
  return { total }; // Consistent!
});

// ✅ EVEN BETTER: Use map for parallel processing
export const handler = withDurableExecution(async (event, context) => {
  const results = await context.map(
    items,
    async (ctx, item) => {
      await ctx.step(async () => saveItem(item));
      return item.price;
    }
  );
  
  const total = results.getResults().reduce((sum, price) => sum + price, 0);
  return { total };
});
```

------
#### [ Python ]

```
# ❌ WRONG: Mutations lost on replay
@durable_execution
def handler(event, context: DurableContext):
    total = 0
    
    for item in items:
        context.step(
            lambda _: save_item_and_mutate(item, total),  # ⚠️ Mutation lost on replay!
            name=f'save-item-{item["id"]}'
        )
    
    return {'total': total}  # Inconsistent value!

# ✅ CORRECT: Accumulate with return values
@durable_execution
def handler(event, context: DurableContext):
    total = 0
    
    for item in items:
        total = context.step(
            lambda _: save_item_and_return_total(item, total),
            name=f'save-item-{item["id"]}'
        )
    
    return {'total': total}  # Consistent!

# ✅ EVEN BETTER: Use map for parallel processing
@durable_execution
def handler(event, context: DurableContext):
    def process_item(ctx, item):
        ctx.step(lambda _: save_item(item))
        return item['price']
    
    results = context.map(items, process_item)
    total = sum(results.get_results())
    
    return {'total': total}
```

------

## Design para idempotência
<a name="durable-idempotency"></a>

As operações podem ser executadas várias vezes devido a novas tentativas ou repetições. Operações não idempotentes causam efeitos colaterais duplicados, como cobrar duas vezes dos clientes ou enviar vários e-mails.

**Use tokens de idempotência:** gere tokens dentro das etapas e inclua-os em chamadas externas de API para evitar operações duplicadas.

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Generate idempotency token once
    const idempotencyToken = await context.step('generate-idempotency-token', async () => {
      return crypto.randomUUID();
    });
    
    // Use token to prevent duplicate charges
    const charge = await context.step('charge-payment', async () => {
      return paymentService.charge({
        amount: event.amount,
        cardToken: event.cardToken,
        idempotencyKey: idempotencyToken
      });
    });
    
    return { statusCode: 200, charge };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext
import uuid

@durable_execution
def handler(event, context: DurableContext):
    # Generate idempotency token once
    idempotency_token = context.step(
        lambda _: str(uuid.uuid4()),
        name='generate-idempotency-token'
    )
    
    # Use token to prevent duplicate charges
    def charge_payment(_):
        return payment_service.charge(
            amount=event['amount'],
            card_token=event['cardToken'],
            idempotency_key=idempotency_token
        )
    
    charge = context.step(charge_payment, name='charge-payment')
    
    return {'statusCode': 200, 'charge': charge}
```

------

**Use a semântica de no máximo uma vez:** para operações críticas que nunca devem ser duplicadas (transações financeiras, deduções de estoque), configure o modo de execução de no máximo uma vez.

------
#### [ TypeScript ]

```
// Critical operation that must not duplicate
await context.step('deduct-inventory', async () => {
  return inventoryService.deduct(event.productId, event.quantity);
}, {
  executionMode: 'AT_MOST_ONCE_PER_RETRY'
});
```

------
#### [ Python ]

```
# Critical operation that must not duplicate
context.step(
    lambda _: inventory_service.deduct(event['productId'], event['quantity']),
    name='deduct-inventory',
    config=StepConfig(execution_mode='AT_MOST_ONCE_PER_RETRY')
)
```

------

**Idempotência do banco de dados:** use padrões de verificação antes da gravação, atualizações condicionais ou operações de atualização para evitar registros duplicados.

## Gerencie o estado de forma eficiente
<a name="durable-state-management"></a>

Cada ponto de verificação salva o estado no armazenamento persistente. Objetos de estado grandes aumentam os custos, diminuem o controle e afetam a performance. Armazene somente dados essenciais de coordenação do fluxo de trabalho.

**Mantenha o estado mínimo:**
+ Armazene IDs e referências, não objetos completos
+ Obtenha dados detalhados em etapas, conforme necessário
+ Use o Amazon S3 ou o DynamoDB para dados grandes, passe referências no estado
+ Evite passar grandes cargas úteis entre as etapas

------
#### [ TypeScript ]

```
import { withDurableExecution, DurableContext } from '@aws/durable-execution-sdk-js';

export const handler = withDurableExecution(
  async (event: any, context: DurableContext) => {
    // Store only the order ID, not the full order object
    const orderId = event.orderId;
    
    // Fetch data within each step as needed
    await context.step('validate-order', async () => {
      const order = await orderService.getOrder(orderId);
      return validateOrder(order);
    });
    
    await context.step('process-payment', async () => {
      const order = await orderService.getOrder(orderId);
      return processPayment(order);
    });
    
    return { statusCode: 200, orderId };
  }
);
```

------
#### [ Python ]

```
from aws_durable_execution_sdk_python import durable_execution, DurableContext

@durable_execution
def handler(event, context: DurableContext):
    # Store only the order ID, not the full order object
    order_id = event['orderId']
    
    # Fetch data within each step as needed
    context.step(
        lambda _: validate_order(order_service.get_order(order_id)),
        name='validate-order'
    )
    
    context.step(
        lambda _: process_payment(order_service.get_order(order_id)),
        name='process-payment'
    )
    
    return {'statusCode': 200, 'orderId': order_id}
```

------

## Projete etapas eficazes
<a name="durable-step-design"></a>

As etapas são a unidade fundamental de trabalho em funções duráveis. Etapas bem projetadas facilitam a compreensão, a depuração e a manutenção dos fluxos de trabalho.

**Princípios do projeto de etapas**
+ **Use nomes descritivos**: nomes como `validate-order` em vez de `step1` tornam os logs e os erros mais fáceis de entender
+ **Mantenha os nomes estáticos**: não use nomes dinâmicos com timestamps ou valores aleatórios. Os nomes das etapas devem ser determinísticos para a reprodução
+ **Equilibre a granularidade**: divida operações complexas em etapas focadas, mas evite pequenas etapas excessivas que aumentem a sobrecarga do ponto de verificação
+ **Operações relacionadas a grupos**: as operações que devem ter êxito ou falhar juntas pertencem à mesma etapa

## Use as operações de espera com eficiência
<a name="durable-wait-operations"></a>

As operações de espera suspendem a execução sem consumir recursos ou incorrer em custos. Use-as em vez de manter o Lambda em execução.

**Esperas com base no tempo:** use `context.wait()` para retardos em vez de `setTimeout` ou `sleep`.

**Retornos de chamada externos:** use `context.waitForCallback()` ao esperar por sistemas externos. Sempre defina tempos limite para evitar esperas indefinidas.

**Sondagem:** use `context.waitForCondition()` com recuo exponencial para sondar serviços externos sem sobrecarregá-los.

------
#### [ TypeScript ]

```
// Wait 24 hours without cost
await context.wait({ seconds: 86400 });

// Wait for external callback with timeout
const result = await context.waitForCallback(
  'external-job',
  async (callbackId) => {
    await externalService.submitJob({
      data: event.data,
      webhookUrl: `https://api.example.com/callbacks/${callbackId}`
    });
  },
  { timeout: { seconds: 3600 } }
);
```

------
#### [ Python ]

```
# Wait 24 hours without cost
context.wait(86400)

# Wait for external callback with timeout
result = context.wait_for_callback(
    lambda callback_id: external_service.submit_job(
        data=event['data'],
        webhook_url=f'https://api.example.com/callbacks/{callback_id}'
    ),
    name='external-job',
    config=WaitForCallbackConfig(timeout_seconds=3600)
)
```

------

## Considerações adicionais
<a name="durable-additional-considerations"></a>

**Tratamento de erros:** faça uma nova tentativa em falhas transitórias, como tempos limite de rede e limites de taxa. Não tente novamente falhas permanentes, como entrada inválida ou erros de autenticação. Configure estratégias de novas tentativas com o máximo de tentativas e taxas de recuo apropriadas. Para obter exemplos detalhados, consulte [Tratamento de erros e novas tentativas](durable-execution-sdk-retries.md).

**Performance:** minimize o tamanho do ponto de verificação armazenando referências em vez de cargas úteis completas. Use `context.parallel()` e `context.map()` para executar operações independentes simultaneamente. Execute operações relacionadas em lotes para reduzir a sobrecarga dos pontos de verificação.

**Versionamento:** invoque funções com números de versão ou aliases para fixar execuções em versões de código específicas. Certifique-se de que as novas versões do código possam tratar o estado das versões mais antigas. Não renomeie etapas nem altere seu comportamento de forma a interromper a reprodução.

**Serialização:** use tipos compatíveis com JSON para entradas e resultados da operação. Converta datas em sequências ISO e objetos personalizados em objetos simples antes de passá-los para operações duráveis.

**Monitoramento:** habilite o registro em log estruturado com IDs de execução e nomes de etapas. Configure os alarmes do CloudWatch para as taxas de erro e a duração da execução. Use rastreamento para identificar gargalos. Para obter orientação detalhada, consulte [Monitoramento e depuração](durable-monitoring.md).

**Testes:** teste o caminho ideal, o tratamento de erros e o comportamento de reprodução. Teste cenários de tempo limite para retornos de chamada e esperas. Use testes locais para reduzir o tempo de iteração. Para obter orientação detalhada, consulte [Testes de funções duráveis](durable-testing.md).

**Erros comuns a serem evitados:** não aninhe chamadas `context.step()`, use contextos secundários. Encapsule as operações não determinísticas em etapas. Sempre defina tempos limite para retornos de chamada. Equilibre a granularidade das etapas com a sobrecarga do ponto de verificação. Armazene referências em vez de objetos grandes no estado.

## Recursos adicionais
<a name="durable-additional-resources"></a>
+ [Documentação do SDK do Python](https://github.com/aws/aws-durable-execution-sdk-python/tree/main/docs): referência completa da API, padrões de testes e exemplos avançados
+ [Documentação do SDK do TypeScript](https://github.com/aws/aws-durable-execution-sdk-js/tree/main/docs): referência completa da API, padrões de testes e exemplos avançados