Pular para o conteúdo

Hooks de Ciclo de Reload

Nesta página

O pipeline completo de um swap segue a ordem: dispose → executa o novo chunk → mescla → accept__on_reload. Cada etapa é opcional e os erros em qualquer hook são registrados mas nunca abortam o swap.

Notificação pós-swap: __on_reload

A forma mais simples de reagir a um reload é definir pub fn __on_reload(name: str) no módulo. A função é chamada por último, depois de toda a mescla, e é útil para logs estruturados, telemetria ou invalidação de caches secundários.

No exemplo abaixo, plugin.zolo conta quantas vezes foi recarregado e imprime esse contador a cada swap:

Edite a fórmula em process; o hook conta e exibe o número de reloads.

plugin.zolo
Playground
// Feature: __on_reload(name) hook

// Syntax: `pub fn __on_reload(name: str)` — fired AFTER the swap.

// When to use: structured logging, invalidating secondary caches,

// re-emitting status messages, dev telemetry.

//

// Fired last, after the merge and after __hot_accept.

// Errors here are logged but do not abort the swap.


use std::package
use std::stats

let stats = #{reloads: 0}

pub fn process(input: int) -> int {
  // Edit the formula below to see the reload in action.

  return input * 2
}

pub fn __on_reload(name: str) {
  let live = package.loaded["plugin"]
  live.stats.reloads = live.stats.reloads + 1
  print(">>> [hook] module '{name}' reloaded ({live.stats.reloads}x)")
}

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

main.zolo
Playground
// Feature: custom notification on swap

// Syntax: define `pub fn __on_reload(name)` in the module.

// When to use: integrate with your own logging/telemetry system.


use plugin::{process}

fn main() {
  print("ENTER calls process(7). Edit plugin.zolo and watch the hook fire.")
  while true {
    let line = io::read("*l")
    if line is nil || line == "q" {
      break
    }
    print("process(7) = {process(7)}")
  }
}

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

Migração explícita: #[hot_dispose] e #[hot_accept]

Quando a preservação automática por tipo não é suficiente — por exemplo, ao mudar o schema do estado — os atributos @hot_dispose e @hot_accept dão controle total.

@hot_dispose é chamado antes do novo chunk rodar e deve retornar um snapshot de tudo que precisa sobreviver. @hot_accept é chamado depois da mescla e recebe esse snapshot, podendo migrar campos ou reconstruir estruturas derivadas.

Altere o campo version de 2 para 3 e observe a migração sendo aplicada.

cache.zolo
Playground
// Feature: explicit migration with __hot_dispose / __hot_accept

// Syntax: `#[hot_dispose] fn ...` and `#[hot_accept] fn ...(prev: any)`.

// When to use: the state's schema changed, OR we want to rebuild

// derived caches, OR the preservation defaults are not sufficient.

//

// Pipeline:

//   1. BEFORE the swap: we call `dispose` -> returns a snapshot.

//   2. New chunk runs (fresh state).

//   3. AFTER the merge: `accept(snapshot)` re-installs / migrates.


use std::package

let entries: any = #{}
let version: int = 2

pub fn add(key: str, value: any) {
  let live = package.loaded["cache"]
  live.entries[key] = value
}

pub fn dump() {
  let live = package.loaded["cache"]
  var n = 0
  for (_, _) in live.entries {
    n = n + 1
  }
  print("cache: {n} entries, schema v{live.version}")
}

@hot_dispose
fn save_state() -> any {
  let live = package.loaded["cache"]
  print(">>> dispose: capturing {live.version}")
  return #{
    entries: live.entries,
    version: live.version,
  }
}

@hot_accept
fn load_state(prev: any) {
  let live = package.loaded["cache"]
  if prev == nil {
    print(">>> accept: no previous state, skipping")
    return
  }
  if prev.version == live.version {
    // same schema: full migration.

    live.entries = prev.entries
    print(">>> accept: schema v{prev.version} preserved in full")
  } else {
    // different schema: copy compatible fields.

    live.entries = prev.entries ?? #{}
    print(">>> accept: migrated v{prev.version} -> v{live.version}")
  }
}

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

main.zolo
Playground
// Feature: controlled state migration

// Syntax: `#[hot_dispose]` + `#[hot_accept]` in the module.

// When to use: schema migration, explicit rebuild, fine control

// when the preservation defaults are not enough.


use cache::{add, dump}

fn main() {
  add("user:1", #{name: "Ana"})
  add("user:2", #{name: "Bia"})
  dump()
  print("ENTER reprints. Edit cache.zolo (e.g. change format or bump version) and save.")
  while true {
    let line = io::read("*l")
    if line is nil || line == "q" {
      break
    }
    dump()
  }
}

Requer a CLI/host do Zolo — abra no playground ou rode localmente.

Desafio

No módulo cache.zolo, adicione um campo created_at: str = "unknown" ao snapshot dentro de @hot_dispose e faça @hot_accept registrá-lo no print. Confirme que o valor aparece corretamente mesmo após múltiplos reloads.

Buscar no Zolo

9 resultados

enespt-br