> 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/construa/conceitos/versoes-com-execucoes-em-andamento.md).

# Versões com execuções em andamento

Uma execução que hibernou há três dias é retomada pelo código da versão em que ela começou: se `SKAIL_WORKLOAD` era `faturamento:v1.0.0`, é a `v1.0.0` que precisa estar publicada quando ela acordar. Esta página explica o que pode mudar nesse código sem quebrar a retomada, o que não pode, e como versionar quando precisa mudar o fluxo.

## Por que isso é um problema

A retomada é um replay: o runtime chama a function desde o início e confere cada `await` contra o histórico gravado. O histórico tem a sequência de passos da versão do código que começou a execução. Se o código publicado agora alcança um `await` diferente na mesma posição, o replay diverge e o runtime lança um erro de não determinismo. Ver [Determinismo e replay](/construa/conceitos/replay-e-determinismo.md).

Cada function tem um endereço, a URI, formada por `nome-do-workload:versao/metodo`, com o nome do método exatamente como está no código (por exemplo `faturamento:v1.0.0/EmitirFatura`). A versão vem de `SKAIL_WORKLOAD`. Uma execução em andamento referencia as URIs da versão em que começou, e é para elas que a retomada é endereçada.

## O que pode mudar sem versionar

O corpo de um command. O command roda de novo só se ainda não gravou resultado; para os que já gravaram, o novo código nem é executado. Trocar a implementação de `CobrarCartao`, corrigir um bug de serialização, mudar a URL do gateway: tudo seguro.

Lógica pura dentro da function que não altera a sequência de `await`s: mensagens de log, cálculos intermediários, nomes de variáveis.

Adicionar functions e commands novos que só as execuções novas vão chamar.

## O que não pode mudar sem versionar

Dentro de uma function com execuções em andamento:

* inserir ou remover um `await` (de um command ou de uma das primitivas de espera do SDK: delay, espera por evento, esperar todos, esperar o primeiro);
* trocar a ordem deles;
* trocar um command por outro na mesma posição;
* mudar a condição de um `if` que decide qual `await` vem em seguida a partir de dados que já estão no histórico;
* renomear o método da function ou de um command chamado por ela (o nome faz parte da URI gravada);
* mudar `SKAIL_WORKLOAD` para um nome ou versão diferente sem manter a anterior.

{% hint style="warning" %}
O sintoma é sempre o mesmo: um erro de não determinismo (`SkailNonDeterministicException` em C#, `SkailNonDeterministicError` em TypeScript) ou "Target method not found" na retomada das execuções antigas. As novas funcionam; as que estavam hibernadas quebram.
{% endhint %}

## Como versionar

Há duas ferramentas.

Versão do workload. `SKAIL_WORKLOAD=faturamento:v1.1.0` publica todas as functions e commands sob URIs novas. As execuções iniciadas na `v1.0.0` continuam endereçadas a `faturamento:v1.0.0/...` e são retomadas só por ela; não há migração automática para a versão nova. A `v1.0.0` precisa continuar publicada e rodando até a última dessas execuções terminar.

Versão do método, com endereço explícito (`skailMethodName` em C#, opção `uri` em TypeScript). Quando só uma function mudou, mantenha a antiga e crie a nova com URI explícita:

{% tabs %}
{% tab title="C#" %}
{% code lineNumbers="true" %}

```csharp
[SkailFunction(skailMethodName: "EmitirFatura")]        // fluxo antigo, mantido até as execuções em andamento terminarem
public async SkailTask EmitirFaturaV1(Guid faturaId) { ... }

[SkailFunction(skailMethodName: "EmitirFaturaV2")]      // fluxo novo, é para este que os novos triggers apontam
public async SkailTask EmitirFatura(Guid faturaId) { ... }
```

{% endcode %}
{% endtab %}

{% tab title="TypeScript" %}
{% code lineNumbers="true" %}

```typescript
import { SkailFunction } from "@skail/runtime";

export class Faturamento {
  @SkailFunction({ uri: "faturamento:v1.0.0/EmitirFatura" }) // fluxo antigo, mantido até as execuções em andamento terminarem
  async emitirFaturaV1(faturaId: string): Promise<void> {
    /* ... */
  }

  @SkailFunction({ uri: "faturamento:v1.0.0/EmitirFaturaV2" }) // fluxo novo, é para este que os novos triggers apontam
  async emitirFatura(faturaId: string): Promise<void> {
    /* ... */
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
Em C#, o `skailMethodName` aceita só o nome (`workload/nome`) ou `nome:versao/metodo` para apontar para outra imagem; em TypeScript, a opção `uri` recebe o endereço no formato `imagem:versao/metodo`. Ver a [referência da function](/referencia/sdk-csharp/skailfunction.md).
{% endhint %}

## O procedimento que recomendamos

<figure><img src="https://1898946878-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsJmS5ILPG5x2x5j0WyiV%2Fuploads%2FuUwttfjVLol9nJALjC19%2Fap-versionamento.svg?alt=media" alt="Linha do tempo de duas versões da mesma function. O fluxo antigo, faturamento:v1.0.0/EmitirFatura, tem execuções em andamento, uma numa espera por evento e outra num delay de 30 dias, com o command seguinte ainda pendente; você vê isso no Monitor, cria o fluxo novo, faturamento:v1.0.0/EmitirFaturaV2, e aponta os novos triggers para ele. O fluxo antigo continua publicado até a última execução dele terminar e é removido quando o Monitor mostra zero execuções."><figcaption></figcaption></figure>

1. Antes de mudar o fluxo de uma function, veja no Monitor se há execuções em andamento ou hibernadas dela. Se não há, mude à vontade.
2. Se há, não edite a function: crie a nova versão (método novo com endereço explícito, ou nova versão do workload) e aponte os novos triggers para ela.
3. Mantenha a versão antiga publicada até a última execução dela terminar. Fluxos com esperas longas (um delay de 30 dias, uma espera por evento sem prazo) podem manter a versão antiga viva por semanas; conte com isso ao planejar.
4. Remova a versão antiga quando o Monitor mostrar zero execuções nela.

{% hint style="info" %}
Se você já mudou e as execuções antigas quebraram: elas aparecem no Monitor como falhas com erro de não determinismo. Publique de volta a versão antiga da function (com o mesmo nome e a mesma sequência de `await`s) e retome-as manualmente.
{% endhint %}

## Próximos passos

[Como fazer deploy de uma nova versão do workload](/opere/configurar-e-hospedar/fazer-deploy-de-uma-nova-versao.md) tem os passos no portal e na pipeline. [Deploy sem quebrar execuções em andamento](/opere/deploy-sem-quebrar-execucoes.md) é o checklist para produção. A [referência da function](/referencia/sdk-csharp/skailfunction.md) detalha o endereço explícito.
