Saltar al contenido

Hooks del Ciclo de Reload

En esta página

El pipeline completo de un swap sigue este orden: dispose → ejecuta el nuevo chunk → fusiona → accept__on_reload. Cada etapa es opcional y los errores en cualquier hook se registran pero nunca abortan el swap.

Notificación post-swap: __on_reload

La forma más sencilla de reaccionar a un reload es definir pub fn __on_reload(name: str) en el módulo. La función se llama al final, después de toda la fusión, y es útil para logs estructurados, telemetría o invalidación de cachés secundarios.

En el ejemplo siguiente, plugin.zolo cuenta cuántas veces ha sido recargado e imprime ese contador en cada swap:

Edita la fórmula en process; el hook cuenta y muestra el 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)")
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo 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)}")
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

Migración explícita: #[hot_dispose] y #[hot_accept]

Cuando la preservación automática por tipo no es suficiente — por ejemplo, al cambiar el schema del estado — los atributos @hot_dispose y @hot_accept otorgan control total.

@hot_dispose se llama antes de que el nuevo chunk se ejecute y debe retornar un snapshot de todo lo que necesita sobrevivir. @hot_accept se llama después de la fusión y recibe ese snapshot, pudiendo migrar campos o reconstruir estructuras derivadas.

Cambia el campo version de 2 a 3 y observa la migración aplicándose.

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}")
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo 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()
  }
}

Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.

Desafío

En el módulo cache.zolo, agrega un campo created_at: str = "unknown" al snapshot dentro de @hot_dispose y haz que @hot_accept lo registre en el print. Confirma que el valor aparece correctamente incluso tras múltiples reloads.

Buscar en Zolo

9 resultados

enespt-br