> ## 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.

# Arquitetura do backend

> Módulos, eventos de domínio e o caminho completo de uma execução

O backend do Hub (`api.hub.dommed`) é um monolito modular: um único serviço, dividido internamente em módulos que não acessam os dados uns dos outros diretamente. Hoje são quatro:

* **identity**: autenticação e cadastro de pessoas usuárias.
* **sector**: o catálogo de setores usados para classificar automações.
* **automation**: o catálogo de automações. O worker (a máquina dedicada de cada automação) é tratado como parte da automação, não como um módulo próprio: uma automação só existe no catálogo quando já tem para onde rodar, então os dois nascem juntos.
* **job**: cada execução de uma automação.

Dentro de cada módulo, as entidades principais (`User`, `Sector`, `Automation`) são donas das próprias mudanças de estado: toda alteração relevante gera um evento de domínio, guardado junto com a mudança que o originou. É esse registro que alimenta a comunicação entre módulos, descrita abaixo.

Nenhum registro é apagado de verdade no banco: desativar algo (uma automação, um setor, uma pessoa usuária) marca o registro como inativo, sem excluí-lo.

## Comunicação entre módulos: eventos e o padrão Outbox

Quando um módulo precisa reagir a algo que aconteceu em outro, isso acontece por evento, não por chamada direta. O problema que esse desenho resolve: se a API publicasse o evento diretamente numa fila de mensagens no meio da requisição, uma falha de rede nesse instante deixaria o sistema inconsistente, a mudança salva no banco mas ninguém avisado dela.

A solução é gravar o evento na mesma transação de banco que a mudança que o gerou (por exemplo, `JobCreated` é gravado junto com o `Job` novo). Um processo separado, o Outbox Relay, varre esses eventos pendentes a cada 2 segundos e os publica de fato na fila (RabbitMQ, exchange `dom_med`, uma chave de roteamento por tipo de evento). Se a publicação falhar, o evento continua marcado como pendente e é tentado de novo no próximo ciclo. O evento só é considerado entregue depois de publicado com sucesso.

Eventos hoje incluem, entre outros, `JobCreated` (dispara o fluxo de execução descrito abaixo) e `WorkerRegistered`/`WorkerDeactivated` (mudanças na máquina dedicada de uma automação, tratadas como eventos da própria automação, não de um módulo separado).

## O caminho de uma execução

Do disparo ao resultado, uma execução passa pelos seguintes passos:

1. Uma pessoa dispara uma execução (`POST /jobs`). O job é criado com status pendente, e o evento `JobCreated` é gravado na mesma transação.
2. O Outbox Relay publica esse evento na fila de mensagens.
3. Em paralelo, a API tenta ligar a máquina dedicada daquela automação. Essa chamada não bloqueia a resposta: a execução já foi confirmada antes disso terminar.
4. O worker consome o evento assim que a máquina liga. Se a máquina já estava ligada quando o job foi criado, ou se ligou antes do evento chegar, o worker também confere periodicamente se há jobs pendentes, para não depender só da fila.
5. O worker reivindica o job (`POST /jobs/{id}/start`). Se outro worker já reivindicou, ou a automação está no limite de execuções simultâneas, a reivindicação é recusada e isso é esperado, não um erro.
6. O worker executa e reporta o resultado: sucesso (`POST /jobs/{id}/complete`) ou falha (`POST /jobs/{id}/fail`).

## Serviços de segundo plano

Dois processos rodam continuamente ao lado da API:

* **Outbox Relay**: publica eventos pendentes a cada 2 segundos, em lotes.
* **Monitor de jobs presos**: a cada 30 segundos, reenvia o comando de ligar a máquina para jobs que estão pendentes há mais de 3 minutos. Esse monitor cobre apenas jobs presos em pendente, o caso de a máquina não ter respondido à primeira tentativa de ligar. Um job que já está em execução e trava porque a máquina falhou no meio do processo não é coberto por nenhum monitor automático hoje (ver [Executar uma automação](/operations/executar), seção sobre execuções presas). São dois problemas diferentes: um reage a uma máquina que não ligou, o outro seria sobre uma máquina que ligou e depois parou de responder, e só o primeiro existe hoje.

## Modelo de dados

As tabelas principais seguem os módulos de perto: `users`, `refresh_tokens`, `sectors`, `automations`, `workers` (um por automação), `jobs`, `events` (a fila de eventos do Outbox). Não existe uma tabela separada para passos de execução dentro de um job: cada job é uma unidade só, do início ao fim.
