evoke Get started

Examples · 05 of 06

A runbook where each step names the next.

Drain, fail over, verify. Each step's program returns the next sentence, and a six-line loop submits it. Every hop passes the gate on its own, and only the destructive one stops for a person. A pattern for your app. The database bodies shown are stand-ins that return fixed lines.

The request and the result

01

Three steps, one sentence typed.

The person types the first step. The program names the second, and the second names the third. Every line is what Node printed.

~/runbook
$ node runbook.ts "drain the primary" primary drained Promote the replica now? [y]es [n]o > y replica promoted writes landing on the new primary
  1. 1A step names the next. The program returns data.next, a sentence. The loop submits it as if a person had typed it.
  2. 2Every hop passes the bar. Drain is a write, verify is a read. Each was decided and gated on its own.
  3. 3Only the failover asks. It is destructive, so it confirms every time, however sure the classifier was.

The operations

02

Three reflexes and a loop.

A manifest and a body per step, as files or as code. The loop is the whole application: while there is a next sentence, handle it.

drain/reflex.tomlthe author's
reflex = 1

description = """
Drain traffic from the primary database.
New connections go to the replica; open ones finish."""
effect  = "write"
confirm = "Drain the primary?"
run     = "drain.mts"

[examples]
"drain the primary" = {}
drain/drain.mtsthe author's
import type { Reflex } from "./reflex.d.ts"

export default (async () => ({
  text: "primary drained",
  data: { next: "fail over to the replica" },
})) satisfies Reflex
  1. 1The bodies are stand-ins. Each returns its line and the next sentence. Yours would drain, promote and check a real database.
  2. 2The loop stops the moment a step does not run. A no, an abstain or a failure ends it. Nothing after runs, and nothing before is undone.
  3. 3The same loop over files or code. load takes a root with evoke.toml, or the reflexes handed as objects.

One boundary

03

The destructive step waits for a yes.

The failover cannot be undone from where it runs, so its manifest says destructive. Answer no, and the loop ends there. The drain stays done. The verify never runs.

node
$ node runbook.ts "drain the primary"
primary drained
Promote the replica now?  [y]es [n]o > n

The question is the reflex's own confirm line. A confirm handler that returns false makes handle() answer declined, and the loop's break does the rest. handle, in the manual →

Before you run it

04

What this pattern needs.

The files above are the whole example. Copy them from this page.