> For the complete documentation index, see [llms.txt](https://docs.skail.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.skail.dev/quickstart/mais-exemplos-praticos/fluxo-de-aprovacao-com-timeout.md).

# Fluxo de aprovação (com timeout)

Muitos sistemas precisam lidar com algo simples, mas chato de implementar:

* enviar um e-mail
* esperar o usuário responder
* e seguir o fluxo com base nisso
* ou tomar uma ação automática se ele não responder

No legado, isso normalmente vira uma mistura de:

* tabela de controle
* job rodando de tempos em tempos
* lógica de timeout manual
* retries espalhados

Com o skail, isso vira um código direto simples.

### Esperando aprovação com prazo

Imagine um fluxo de aprovação simples:

1. você envia um e-mail com um link
2. espera o usuário aprovar
3. se ele aprovar → segue o fluxo
4. se não responder em 72h → expira

No skail, isso vira uma função linear:

```csharp
[SkailFunction]
public async SkailTask WaitForApprovalWithTimeout(Guid approvalId)
{
    await SendApprovalEmail(approvalId);

    var approvalTask = SkailEvent.WaitForEvent<ApprovalResponse>("EVT_APPROVAL", approvalId);
    var timeoutTask = SkailTask.DelayHours(72);

    var result = await SkailTask.WhenAny(approvalTask, timeoutTask);

    if (result == approvalTask)
        await NotifyApproved(approvalId);
    else
        await NotifyExpired(approvalId);
}
```

### O que está acontecendo aqui

O fluxo é simples de ler:<br>

1. envia o e-mail
2. espera duas coisas ao mesmo tempo:
   1. o usuário responder
   2. ou, o tempo expirar
3. segue baseado no que acontecer primeiro

**Sem jobs, sem polling, sem tabela de controle, só código de regra de negócio.**

### Enviando o e-mail (sem mudar seu legado)

A chamada para enviar o e-mail continua sendo uma integração normal:

```csharp
[SkailCommand]
public async SkailTask SendApprovalEmail(Guid approvalId)
{
    var link = $"https://portal.company.com/approve/{approvalId}";
    await EmailService.SendAsync("Approval Required", $"Click here to approve: {link}");
}
```

Ou seja:

* você continua usando seus serviços atuais
* sem precisar reescrever nada

### Como o usuário responde

Quando o usuário clica no link, seu sistema só precisa disparar um evento:

* pode ser via HTTP
* webhook
* no skail basta chamar FireEvent()
* ou qualquer outro mecanismo

Algo como:

```csharp
await SkailEvent.FireEvent(
    "EVT_APPROVAL",
    approvalId.ToString(),
    new ApprovalResponse { Approved = true }
);
```

E pronto — a execução continua de onde parou.

### Por que isso é relevante

No modelo tradicional, esse tipo de fluxo costuma ser difícil de manter:

* estado espalhado
* lógica de timeout manual
* difícil de entender o que está acontecendo

Aqui, tudo fica explícito:

* **o fluxo está em um único lugar**
* o estado é controlado automaticamente
* o tempo não depende de job rodando

### E se demorar dias?

Não importa.

A execução pode ficar “pausada” por horas ou dias, sem consumir recurso, e continua exatamente de onde parou quando o evento chega, com todas as variáveis e contexto (como se nunca tivesse parado).

### Resultado

Você transforma algo que normalmente é:

* complexo
* frágil
* difícil de debugar

...em um fluxo simples de ler e manter.

Sem falar na facilidade de depurar com o Time Travel Debug, como qualquer outro código skail.
