> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vertgroup.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Workers

> Como um worker reivindica, executa e reporta um job

Cada automação roda como um processo dedicado, em uma máquina dedicada: um worker atende exatamente uma automação, nunca várias. O código dos workers vive em um repositório separado da API (`workers.hub.dommed`), para que a falha, o deploy ou a escala de uma automação não afetem a API nem as outras automações.

Esse repositório reúne duas coisas no mesmo processo: uma base reutilizável (configuração, cliente HTTP, o contrato de execução, o consumidor da fila de mensagens) e o código específico de cada automação que já existe. Não é distribuído como pacote separado: um repositório por automação e um pacote instalável já foram tentados e revertidos, porque a complexidade extra não se pagava com uma automação só rodando.

## Como um worker recebe trabalho

Um worker se autentica em todas as chamadas com uma chave própria (`X-Worker-Api-Key`), obtida uma única vez no momento em que a máquina é registrada.

Existem dois caminhos para um worker descobrir que há um job para rodar:

* **Ao vivo**: a API publica o evento `JobCreated` quando o job é criado. Todo worker se conecta à mesma fila e ouve todo evento desse tipo, não só os da própria automação: é na hora de reivindicar o job que a automação errada é recusada, não antes.
* **Na inicialização**: antes de conectar para receber eventos, o worker consulta os jobs pendentes daquela automação (`GET /jobs/pending`). Isso cobre o caso de um job ter sido criado enquanto a máquina ainda estava desligada, quando não havia ninguém ouvindo o evento.

Os dois caminhos convergem no mesmo passo: o worker tenta reivindicar o job (`POST /jobs/{id}/start`). Se a reivindicação falhar porque outro worker já pegou o job, a automação está no limite de execuções simultâneas, ou a automação está em modo desenvolvimento, isso é um resultado esperado (recusa), não uma falha do worker.

## Contrato de execução

Uma automação implementa uma única função: recebe o identificador do job, o identificador da automação e o contexto (os dados enviados no disparo, já validados pela API contra o formulário daquela automação), e devolve um resultado.

O valor devolvido é reportado como sucesso (`POST /jobs/{id}/complete`). Se a função lançar um erro, ele é reportado como falha (`POST /jobs/{id}/fail`), com a mensagem do erro. Fora reportar o resultado, essa função não fala diretamente com a API: quem cuida de reivindicar, confirmar e reportar é a camada que consome a fila, não o código de cada automação.

## Concorrência e encerramento

Cada worker limita quantos jobs roda ao mesmo tempo com um controle local, hoje redundante com o limite que a própria API já aplica (`max_concurrent_jobs` da automação): os dois existem porque o controle local nasceu antes do controle do lado da API, e não foi removido.

Quando a máquina recebe um sinal de desligamento, o worker espera um período de carência configurável (2 minutos por padrão) para jobs em andamento terminarem antes de forçar o encerramento dos que sobrarem, para que nenhum job fique marcado como em execução para sempre. Não existe mais um sinal periódico de "worker vivo": o status de cada worker é definido inteiramente pelas ações de ligar e desligar feitas pela API, não por algo que o worker reporta sozinho.
