Automações

Execução Paralela

Diferentemente da execução sequencial, a execução paralela permite que duas ou mais instâncias ou ramificações avancem ao mesmo tempo. Em plataformas como Home Assistant e Node-RED, isso reduz latência quando ações são independentes, como acionar luz, áudio e notificação em paralelo. A consequência prática é resposta mais rápida. O risco é concorrência sobre o mesmo dispositivo, variável ou arquivo; sem limites, isolamento e idempotência, surgem estados finais imprevisíveis e consumo excessivo de recursos.


⚙ Definição Técnica
Execução paralela é um modo de processamento no qual duas ou mais instâncias de uma automação, ou duas ou mais ramificações dentro da mesma instância, podem executar ações sobrepostas no tempo. A finalidade é reduzir espera quando as etapas são independentes ou quando novos eventos não devem aguardar a conclusão de execuções anteriores. O mecanismo não implica necessariamente uso de múltiplos núcleos de CPU; em muitos motores, a concorrência é cooperativa e baseada em tarefas assíncronas. Para o projeto, importa que os efeitos possam intercalar. Se duas instâncias escrevem no mesmo dispositivo, variável, arquivo ou serviço, a ordem final pode variar. Plataformas como Home Assistant oferecem modo parallel com limite máximo de execuções; Node-RED pode processar mensagens concorrentes conforme o fluxo; sistemas baseados em JavaScript, Python assíncrono ou workers usam filas e tarefas. O modo deve ser escolhido apenas quando a lógica tolera sobreposição ou possui controles de concorrência.
Tipos comuns de gatilhos
Instâncias paralelas da mesma automação
Cada novo gatilho inicia uma nova execução mesmo que a anterior ainda esteja ativa. Isso é útil em notificações independentes, processamento de múltiplos sensores e eventos que não podem ser descartados. Se três portas abrirem em 2 s, três instâncias podem registrar e notificar sem aguardar. O risco aparece quando todas alteram um recurso compartilhado. Uma automação que define volume, reproduz áudio e depois restaura o volume pode terminar com ordem errada se duas instâncias se sobrepõem. A primeira pode restaurar enquanto a segunda ainda reproduz. Para usar o modo, identifique recursos, torne ações idempotentes e defina max. O limite evita explosão quando um sensor ruidoso gera centenas de eventos.
Ramificações paralelas dentro de uma execução
Uma única instância dispara blocos independentes ao mesmo tempo e aguarda todos, alguns ou nenhum, conforme a implementação. Acender luz, enviar notificação e registrar evento podem ocorrer em paralelo. O ganho é aproximadamente limitado pela etapa mais lenta. Três ações de 2 s, 3 s e 5 s levam perto de 5 s em paralelo, em vez de 10 s em sequência, desconsiderando overhead. A dependência precisa ser real: se a mensagem usa o resultado da primeira ação, não pode iniciar antes. Erros também precisam de política. Uma ramificação pode falhar enquanto as outras concluem. O motor deve definir se cancela o conjunto, continua ou agrega erros. Para fluxos críticos, registre resultados individualmente.
Paralelismo por dispositivo ou área
Eventos são particionados por chave lógica. Ações sobre dispositivos diferentes executam em paralelo; ações sobre o mesmo dispositivo permanecem serializadas. Esse desenho combina desempenho e segurança. Um controlador pode processar cozinha e garagem ao mesmo tempo, mas manter uma fila por fechadura. Nem todas as plataformas oferecem partição nativa. Pode-se criar scripts separados, filas por entidade ou locks. A chave precisa ser estável. Usar nome amigável pode falhar após renomeação. Entity_id, device_id ou recurso lógico são preferíveis. O custo é maior complexidade. Em instalações grandes, porém, evita que um evento lento bloqueie toda a casa e reduz condições de corrida locais.
Paralelismo com chamadas externas
A automação inicia várias APIs, webhooks ou serviços simultaneamente. Isso reduz latência total, mas aumenta pico de conexões e pode ultrapassar rate limits. Cinco requisições em paralelo podem ser aceitáveis; cinquenta podem receber HTTP 429. Use limite de concorrência, timeout e backoff. Cada chamada precisa de idempotência quando há retentativa. Se o fluxo depende de todos os resultados, aplique join e prazo máximo. Se apenas um sucesso basta, cancele os demais quando possível. Serviços de nuvem podem responder fora de ordem. A associação deve usar request_id, não posição. Credenciais e logs precisam permanecer isolados.
Paralelismo em automações temporizadas
Rotinas com delays longos frequentemente motivam modo paralelo. Um sensor de movimento inicia luz por 5 min; novo movimento pode iniciar outra instância. Isso pode manter a luz ligada, mas também criar vários timers que desligam em momentos diferentes. O resultado final pode ser incorreto. Para esse caso, restart mode, timer compartilhado ou entidade de ocupação costuma ser melhor. O critério é a semântica do tempo. Se cada evento deve gerar obrigação independente, paralelo funciona. Se todos renovam uma mesma janela, use reinício ou timer. A consequência prática é evitar que a luz apague enquanto ainda há movimento.
Considerações de Implementação
⚠️
Recursos compartilhados criam condições de corrida
Duas execuções podem ler o mesmo estado, calcular decisões e escrever resultados diferentes. O problema não exige threads reais; basta sobreposição temporal. Exemplos: duas rotinas atualizam uma lista, incrementam contador, alteram setpoint ou restauram volume. A ordem observada varia. Locks, filas por recurso, compare-and-set, transações ou idempotência reduzem. Em Home Assistant, helpers não oferecem transação geral. Uma alternativa é centralizar a escrita em script queued. Para dispositivos, prefira comandos de estado final. Toggle é especialmente frágil: duas instâncias podem anular uma à outra. Testes precisam gerar eventos simultâneos e verificar o estado final.
⚠️
Paralelismo sem limite transforma ruído em sobrecarga
Sensor defeituoso, loop ou webhook abusado pode iniciar milhares de instâncias. CPU, memória, conexões, banco e rádio são consumidos. Defina max e comportamento ao exceder: rejeitar, enfileirar, agregar ou descartar. O valor deve refletir capacidade e função. Dez notificações simultâneas podem ser suficientes; processamento de vídeo pode exigir dois. Métricas precisam mostrar execuções ativas, rejeitadas e duração. Alertas detectam anomalia. Rate limiting na origem também ajuda. Limite não corrige loop lógico; apenas reduz impacto.
ℹ️
Ação independente precisa ser comprovada, não presumida
Duas etapas podem parecer independentes e compartilhar dependência oculta. Acender uma luz e capturar imagem podem depender da ordem, porque a câmera precisa da iluminação estabilizada. Enviar mensagem e atualizar banco podem exigir que o registro exista antes do link. O desenho deve mapear entradas, saídas e efeitos. Somente etapas sem relação causal devem executar em paralelo. Quando existe dependência parcial, use grupos: ações independentes em paralelo, join, depois próxima fase. Esse modelo preserva clareza.
ℹ️
Trace deve distinguir instância, ramo e recurso
Concorrência torna diagnóstico mais difícil. Cada execução precisa de run_id. Cada ramo, branch_id. Logs devem incluir trigger_id, recurso e timestamps. Sem isso, mensagens de duas instâncias se misturam. O trace visual deve mostrar sobreposição. Para dados pessoais, redija payload. Métricas de duração por ramo revelam gargalo. Em erro, registre se outras ramificações concluíram. Essa observabilidade é requisito operacional, não detalhe. A execução mais rápida perde valor se a causa de inconsistência não puder ser reconstruída.