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