Pular para o conteúdo

O livro · 07

Resiliência

book.md · 82 linhas · 2 min de leitura

Objetivo: deixar processos falharem e reiniciarem com segurança (supervisão, links e monitors), tudo emergindo da estrutura do código (modelo BEAM, sem behaviours declarados à parte).

Quando um processo morre, a sequência é fixa: rodam os defers dele, libera-se o @mm dele, e produz-se um error que descreve a morte (crash com motivo, ou saída limpa). Esse error é o que chega a quem observa: é o error-as-value aplicado à morte de processo.

Você não precisa de um construto novo pra “ser avisado da morte sem morrer junto”: é o catch |e| do spawn:

@supervisor(max_restarts: 3, window: 10s)
spawn worker(data) catch |e| {
// 'worker' morreu, EU (supervisor) não. 'e' é o motivo. Reajo sem propagar.
log("worker caiu: {{e}}")
}

Como a morte é um error comum, você a discrimina com match |e|:

@supervisor(strategy: rest_for_one)
spawn db(conn) match |e| {
Normal => log("terminou o trabalho")
Crashed(m) => restart()
Timeout => escalate()
}
  • one_for_one: processos independentes, cada um com seu catch. Sem anotação, é o default (sem limite de restarts):
spawn worker_a(da) catch |e| { ... }
spawn worker_b(db) catch |e| { ... } // se A cai, B não sabe
  • one_for_all: um spawn-block, onde os processos vivem e morrem juntos. Se um cai, o coordinator mata os irmãos e reinicia o grupo:
spawn {
indexer(docs) catch |e| { log(e) }
notifier(subs) catch |e| { log(e) }
} catch |e| {
notify_ops("grupo crítico morreu: {{e}}") // o grupo inteiro se esgotou
}
  • rest_for_one: pipeline com ordem; o único que exige anotação (não é inferível):
@supervisor(strategy: rest_for_one)
spawn {
db_connection() // cai → reinicia os três
db_writer() // cai → reinicia writer + reader
db_reader() // cai → reinicia só reader
} catch |e| { ... }

A BEAM tem link/monitor/trap_exit como primitivas; Makoto não as expõe cruas. Acoplar destino é a árvore (processos no mesmo spawn-block compartilham destino porque a estrutura diz isso), e observar sem acoplar é o catch. Cascata de morte invisível some: a árvore de supervisão é o código.

A função do processo é limpa, sem política de retry embutida; o @supervisor no call site decide max_restarts/window. Quando esgota, o catch externo dispara, sem escalação automática.

Próximo: 08 · Memória