Skip to content

Fallback on critical failures

Some Tasks are critical to the app — auth, user data. When one of them fails, everything that reads its result skips. To run something else instead — a fallback page, a retry, a smaller app — add a Task that watches them: a Control Task. Reading .status (not .result) keeps it running even when the critical Tasks fail. It produces a decision, and downstream Tasks use that decision to choose what to do.

Uncomment the throw to see the fallback path run instead:

import { compose, createTask } from "@grlt-hub/app-compose"
// critical to the app
const auth = createTask({
name: "auth",
run: {
fn: () => {
// uncomment to make auth fail
// console shows "fallback shown" instead of "dashboard ready"
// 👇
// throw new Error("[auth]: failed")
return { id: 1 }
},
},
})
// reads critical Task statuses → { ok: boolean }
const control = createTask({
name: "control",
run: {
context: [auth.status],
fn: (statuses) => {
// works for any number of statuses
const passed = statuses.every((status) => status === "done")
return { ok: passed }
},
},
})
const dashboard = createTask({
name: "dashboard",
run: { fn: () => console.log("dashboard ready") },
enabled: {
context: control.result.ok,
fn: (ok) => ok,
},
})
const fallback = createTask({
name: "fallback",
run: { fn: () => console.log("fallback shown") },
enabled: {
context: control.result.ok,
fn: (ok) => !ok,
},
})
compose()
.step(auth)
.step(control)
.step([dashboard, fallback])
.run()

Watch more critical Tasks by adding them to the context array.